Pesquisa de site

javascript - Typescript - como você lida com propriedades comuns entre duas interfaces?


Eu tenho uma interfaceA1 e interfaceB com algumas propriedades em comum

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

interface userData {
  data: string,
  status: string
}

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

Então, existem algumas propriedades como id, versão que são comuns entre interfaceA1 e interfaceB

Eu tenho uma variável do tipo interfaceA com os seguintes valores

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

Eu tenho outra variável do tipo interfaceB, que está apenas declarada

let interfaceBData: interfaceB

Agora eu quero copiar os valores das propriedades comuns de interfaceA1Data para interfaceBData. As propriedades não comuns devem ser adicionadas à propriedade definition. Assim, no final, o interfaceBData terá os seguintes valores.

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

Como alcançar isso em TypeScript?

O transformador deve ser genérico, digamos que eu tenha uma interfaceA2, como converter para o tipo interfaceB. Em todos os casos, a interface de destino é a mesma, apenas a interface de origem difere.

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

interface valueType {
  type: string,
  requester: string
}

Resposta #1

Se houver uma sobreposição intencional entre duas interfaces, pode ser válido extrair propriedades comuns para uma interface separada. Por exemplo:

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
}

Agora, você pode prosseguir criando a interface 'B' da mesma forma que fez antes, apenas estendendo Versioned mais uma vez com a propriedade definition como Objeto:

interface B extends Versioned {
  definition: Object
}

... mas você pode querer fornecer maior rigor transformando-o em uma interface genérica, assim:

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

Agora você pode facilmente escrever uma função transformadora para qualquer tipo/interface que estenda Versioned, transformando isso em uma forma específica de Serialized:

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

Aqui está o link do TS Playground.