Typescript - Hur man skapar en typ med samma egenskaper som ett gränssnitt, men med olika egenskapstyper


Jag skapar en fråga-byggare. Jag har datamodeller som ser ut så här:

export interface SalesOrder {
  id: number
  customerName: string;
  date: Date;
}

I min frågebyggare vill jag att columns ska se ut ungefär så här:

{
  id: 'salesOrder.id',
  customerName: 'customer.name',
  date: 'salesOrder.date',
}

Jag försöker lista ut hur jag kan typsätta Columns-objektet generiskt så att det har alla nycklar från modellen, men alla typer kommer att vara strängar. Så då skulle jag kunna deklarera det som const columns: Columns<SalesOrder> och det skulle förstå att objektet måste ha alla samma nycklar som i SalesOrder-modellen, men med alla värden som string.

Jag försökte detta:

export interface Columns<T> {
  [alias: keyof T]: string;
}

Men det klagar på delen keyof T och säger "En indexsignatur-parameter typ måste antingen vara 'string' eller 'number'."

Svar #1

Slutet på det felmeddelandet borde ha varit:

Överväg att använda en mappad objekttyp istället.

Se dokumentationen om mappade typer.

Här är vad det betyder:

export type Columns<T> = {
  [alias in keyof T]: string;
}

Det behöver vara en type, eftersom detta faktiskt är en mappad typ. Den går igenom alla möjligheter av keyof T och utvärderar varje medlem av den unionen individuellt. Detta stöds egentligen inte i gränssnitt.

Och [key: MyType] är en indexsignatur. Det säger att för vilken MyType som helst finns ett värde av en konsekvent typ. Där [key in MyType] definierar nycklarna i en mappad typ.

Lekplats


Alternativt kan du prova Record-typen.

export type Columns<T> = Record<keyof T, string>

Lekplats