typescript - איך אני יכול לציין חתימת אינדקס של מחלקה שמסננת מפתחות אינדקס מורשים ידועים שהורשו?


אני רוצה ליצור מחלקה שיורשת ממחלקה, ומגדירה חתימת אינדקס לכל התכונות החדשות של המחלקה שלא קיימות במחלקת האב.

שקול מצב שבו תרצה לציין פורמט מסוים לשאילתת חיפוש שיכולה לקבל מערכים של מונחי חיפוש על שדות, ושנובעת ממחלקת שאילתה כללית.

class Query {
  limit = 25;
  offset?: number;
  constructor() { /* do stuff */ }
}

class FieldSearchQuery extends Query {
  [key: Exclude<string, keyof Query>]: string[]; // not valid, but captures the gist
  constructor() { super(); /* do stuff */ }
}

יש לכם רעיונות לאלטרנטיבות? שימו לב שקיימת מחלקת בסיס, והמטרה שלי היא לצמצם את סוג תת-המחלקה כך שהיא תוכל להשתמש בכל ערכי המפתח החדשים שמגיעים שלא חופפים למפתחות של ההורה ושאנחנו נוכל לבצע בדיקת טיפוס לערכים המשויכים לאותם מפתחות לא ידועים כך שיהיו מסוג מוגדר (בדוגמה שלמעלה, מערכי מחרוזות).

אני ממשיך לעיין בתיעוד של סוגים מתקדמים ומרגיש כאילו אני חייב להחמיץ משהו, כי נראה שכל הכלים כדי להשיג זאת קיימים.

עריכה: רק עכשיו הבנתי שיפור אפשרי, שבו ניתן לפחות להוציא מכלול את כל סוגי הערך שאינם קיימים בהורה:

class Query {
  limit = 25;
  offset?: number;
  constructor() { /* do stuff */ }
}

class FieldSearchQuery extends Query {
  [key: string]: Query[keyof Query]|string[]; // valid, but overly broad
  constructor() { super(); /* do stuff */ }
}

תשובה #1

אתה בטוח להיות על הדפוס הנכון כאן? כי אם אתה מציין חתימת אינדקס על מחלקה, זה לא ייחול רק על התכונות של המחלקה אלא גם על כל המתודות.

class B {
  [key: string]: string[]

  foo(): number { // Property 'foo' of type '() => number' is not assignable to string index type 'string[]'.
    return 1
  }
}

דרך אחת להשיג את הפתרון שלך תהיה לעקוב אחר דוגמת סוגי החיתוך בתיעוד של TypeScript.

הפתרון שלי יהיה להכריז על שדה אחד במחלקה שלך, ולציין את סוגו.

type QueryParams = { [key: string]: any } & {
  limit: number
  offset?: number
}

class Query<T extends QueryParams> {
  params: T
  constructor(params: Partial<T>) {
    this.params.limit = params.limit === undefined ? 25 : params.limit
  }
}

type FieldSearchQueryParams = { [key: string]: string[] } & {
  limit: number
  offset?: number
}

class FieldSearchQuery extends Query<FieldSearchQueryParams> {
  constructor(params: Partial<FieldSearchQueryParams>) {
    super(params)
    // do stuff
  }
}