javascript - Typescript - iki arayüz arasındaki ortak özelliklerle nasıl başa çıkarsınız?


Bir interfaceA1 ve bazı ortak özelliklere sahip interfaceB'im var

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

interface userData {
  data: string,
  status: string
}

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

Yani, interfaceA1 ve interfaceB arasında id, version gibi bazı ortak özellikler vardır.

Aşağıdaki değerlere sahip interfaceA türünde bir değişkenim var

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

Sadece deklarasyonu yapılmış başka bir interfaceB türünde değişkenim var

let interfaceBData: interfaceB

Şimdi, interfaceA1Data'dan interfaceBData'ya ortak özelliklerin değerlerini kopyalamak istiyorum. Ortak olmayan özellikler definition özelliğine eklenmelidir. Yani, sonunda interfaceBData aşağıdaki değerleri tutacak.

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

Bunu TypeScript'te nasıl başarabilirim?

Dönüştürücü genel olmalıdır, diyelim ki interfaceA2'im var, bunu interfaceB tipine nasıl dönüştürebilirim. Tüm durumlarda hedef arayüz aynıdır, sadece kaynak arayüz farklıdır.

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

interface valueType {
  type: string,
  requester: string
}

Cevap #1

İki arayüz arasında kasıtlı bir örtüşme varsa, ortak özellikleri ayrı bir arayüze çıkarmak faydalı olabilir. Örneğin:

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
}

Şimdi, daha önce yaptığınız gibi, sadece definition özelliğini Nesne olarak ekleyerek Versioned'i bir kez daha genişleterek 'B' arayüzünü oluşturma yoluna gidebilirsiniz:

interface B extends Versioned {
  definition: Object
}

... ancak bunu bunun yerine genel bir arayüze dönüştürerek ek katılık sağlamayı düşünebilirsiniz, şöyle:

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

Artık Versioned'i genişleten herhangi bir tür/arayüz için bir dönüştürücü fonksiyonu kolayca yazabilir ve bunu Serialized'ın belirli şekline dönüştürebilirsiniz:

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

İşte TS Playground bağlantısı.