javascript - Typescript - איך אתה מתמודד עם תכונות משותפות בין שתי ממשקים?


יש לי ממשק A1 וממשק B עם כמה תכונות משותפות

interface A1 {
  id : string,
  version: number,
  data: userData,
  createdBy: string
}

interface userData {
  data: string,
  status: string
}

interface B {
  id : string,
  version: number,
  definition : JSON
}

אז, יש כמה תכונות כמו id ו-version שמשותפות בין interfaceA1 ל-interfaceB

יש לי משתנה מסוג interfaceA עם הערכים הבאים

let interfaceA1Data: interfaceA1 = {
  id : '123abc',
  version: 1,
  data: {
    data: 'value',
    status: 'value'
  },
  createdBy: 'me'
}

יש לי משתנה נוסף מסוג interfaceB, שהוא רק הוכרז

let interfaceBData: interfaceB

עכשיו אני רוצה להעתיק את הערכים של התכונות המשותפות מ-interfaceA1Data ל-interfaceBData. התכונות שאינן משותפות צריכות להיות מתווספות לתכונת definition. כך, בסופו של דבר interfaceBData יחזיק את הערכים הבאים.

interfaceBData = {
  id : '123abc',
  version: 1,
  definition: {
    data: {
      data: 'value',
      status: 'value'
    },
    createdBy: 'me'
  }
}

איך להשיג את זה ב-TypeScript?

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

interface A2 {
  id : string,
  version: number,
  value: valueType,
  createdBy: string
}

interface valueType {
  type: string,
  requester: string
}

תשובה #1

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

interface Versioned {
  id: string,
  version: number
}

interface userData {
  data: string,
  status: string
}

interface valueType {
  type: string,
  requester: string
}

interface A1 extends Versioned {
  data: userData,
  createdBy: string
}

interface A2 extends Versioned {
  value: valueType,
  createdBy: string
}

עכשיו, אתה יכול להמשיך וליצור את הממשק 'B' באותה הדרך שעשית קודם, פשוט על ידי הרחבת Versioned פעם נוספת עם המאפיין definition כאובייקט:

interface B extends Versioned {
  definition: Object
}

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

interface Serialized<T extends Versioned> extends Versioned {
  definition: Omit<T, keyof Versioned>
}

כעת ניתן בקלות לכתוב פונקציית טרנספורמר לכל סוג/ממשק שמרחיב את Versioned ולהפוך זאת לצורה ספציפית של Serialized:

function transformer<T extends Versioned>(
{id, version, ...args}: T): Serialized<T> {
  return {
    id, version,
    definition: {...args}
  }
}

הנה הקישור ל-TS Playground.