Hvordan kan jeg få et generisk TypeScript-grensesnitt til å arve fra et annet generisk grensesnitt?


Jeg har et grensesnitt, med flere elementer:

export interface Item {
  id: string;
  code: string;
  createdAt: string;
  updatedAt: string;
  level: number;
  seq: number;
  hasChildren: boolean;

  parentObject?: Item;
  children?: Item[];
}

Jeg ønsket noe som Partial<T> som jeg hjelpsomt oppdaget her: Gjør alle egenskaper i et Typescript-grensesnitt valgfrie

Jeg vil imidlertid gjøre ett av feltene obligatorisk. Jeg implementerte dette:

export interface ItemUpdate extends Partial<Item> {
  id: string;
}

og det kompilerte godt. Jeg vil imidlertid unngå å erklære det for hvert grensesnitt. Til det laget jeg det mer generisk:

export interface UpdateOf<T> extends Partial<T> {
  id: string; // the ID is the only mandatory value for an update
}

Men det kompilerer ikke lenger, og returnerer følgende feil:

error TS2312: An interface may only extend a class or another interface.

Jeg kjører Angular 6.1.5, som kommer med Typescript 2.9 (så vidt jeg vet).

Svar #1

Feilmeldingen er utdatert; det er et åpent problem for å oppdatere den. Den gjeldende regelen er at en klasse eller et grensesnitt bare kan utvide en objekttype eller et snitt av objekttyper med statisk kjente medlemmer, siden kompilatoren trenger å sjekke om typene til egenskapene erklært i klassen eller grensesnittet er kompatible med typene til de tilhørende egenskapene (hvis noen) i basetypen. Medlemmene av Partial<Item> er statisk kjente, mens medlemmene av Partial<T> ikke er det. En løsning er å bruke en snittype i stedet for et under-grensesnitt:

export type UpdateOf<T> = Partial<T> & {id: string};

Relaterte artikler