tutorial - typescript wiki




Tornar opcionais todas as propriedades em uma interface TypeScript (3)

Eu tenho uma interface no meu aplicativo:

interface Asset {
  id: string;
  internal_id: string;
  usage: number;
}

que faz parte de uma interface de postagem:

interface Post {
  asset: Asset;
}

Também tenho uma interface destinada a um rascunho posterior, em que o objeto do ativo pode ser apenas parcialmente construído

interface PostDraft {
  asset: Asset;
}

Quero permitir que um objeto PostDraft tenha um objeto de ativo parcial enquanto ainda verifica os tipos nas propriedades existentes (portanto, não quero trocá-lo por any ).

Eu basicamente quero uma maneira de poder gerar o seguinte:

interface AssetDraft {
  id?: string;
  internal_id?: string;
  usage?: number;
}

sem redefinir completamente a interface do Asset . Existe uma maneira de fazer isso? Caso contrário, qual seria a maneira inteligente de organizar meus tipos nessa situação?


Além de David Sherret, responda apenas algumas linhas do meu lado, como ele pode ser implementado diretamente sem o tipo Partial<T> para uma melhor compreensão do assunto.

interface IAsset {
  id: string;
  internal_id: string;
  usage: number;
}

interface IPost {
  asset: IAsset;
}

interface IPostDraft {
  asset: { [K in keyof IAsset]?: IAsset[K] };
}

const postDraft: IPostDraft = {
  asset: {
    usage: 123
  }
};

As propriedades na interface são opcionais ou não, não é possível usar a mesma interface uma vez como opcional e uma vez como deve.

O que você pode fazer é ter uma interface com propriedades opcionais para o AssetDraft e, em seguida, uma classe com propriedades obrigatórias para o Asset :

interface AssetDraft {
    id?: string;
    internal_id?: string;
    usage?: number;
}

class Asset {
    static DEFAULT_ID = "id";
    static DEFAULT_INTERNAL_ID = "internalid";
    static DEFAULT_USAGE = 0;

    id: string;
    internal_id: string;
    usage: number;

    constructor(draft: AssetDraft) {
        this.id = draft.id || Asset.DEFAULT_ID;
        this.internal_id = draft.internal_id || Asset.DEFAULT_INTERNAL_ID;
        this.usage = draft.usage || Asset.DEFAULT_USAGE;
    }
}

Os valores padrão aqui são membros estáticos, mas você pode obtê-los de outras maneiras ou gerar um erro caso estejam ausentes.

Acho isso muito confortável ao trabalhar com jsons recebidos do servidor (ou algo semelhante), as interfaces representam os dados json e as classes são os modelos reais que são construídos usando os jsons como valores iniciais.


Que tal forçar o lançamento de um objeto vazio, por exemplo

const draft = <PostDraft>{}
draft.id = 123
draft.internal_id = 456
draft.usage = 789

Se você realmente precisa disso, sempre poderá gerar uma interface d.ts a partir de um modelo que faça as propriedades opcionais e digitadas.

Como Nitzan apontou, as propriedades da interface Typescript são opcionais ou não





typescript