syntax - Typescript - interface som utökar ett annat interface med nästlade egenskaper
Jag har ett gränssnitt som:
export interface Module {
name: string;
data: any;
structure: {
icon: string;
label: string;
...
}
}
Hur kan jag utöka det, så att jag lägger till några nya egenskaper till strukturen, utan att upprepa mig själv? Måste jag skapa ett nytt gränssnitt för strukturen och utöka det och skapa en ny modul med det nya struktursgränssnittet eller finns det någon annan syntax för att uppnå detta?
Idealiskt skulle jag bara skriva något som:
export interface DataModule extends Module {
structure: {
visible: boolean;
}
}
export interface UrlModule extends Module {
structure: {
url: string;
}
}
Tack!
Svar #1
Gränssnitt kan inte lägga till typer av medlemmar i basgränssnittet (åtminstone inte direkt). Du kan istället använda en snittyptyp:
export interface Module {
name: string;
data: any;
structure: {
icon: string;
label: string;
}
}
export type DataModule = Module & {
structure: {
visible: boolean;
}
}
export type UrlModule = Module & {
structure: {
url: string;
}
}
let urlModule: UrlModule = {
name: "",
data: {},
structure: {
icon: '',
label: '',
url: ''
}
}
De bör bete sig på liknande sätt som gränssnitt, de kan implementeras av klasser och de kommer att kontrolleras när du tilldelar objektliteraler till dem.
Du kan också göra det med gränssnitt, men det är lite mer utförligt och innebär att använda en typfråga för att få den ursprungliga typen av fältet, och återigen en snittning:
export interface DataModule extends Module {
structure: Module['structure'] & {
visible: boolean;
}
}
export interface UrlModule extends Module {
structure: Module['structure'] & {
url: string;
}
}
Det riktigt ordflödiga alternativet (även om det på vissa sätt är enklare att förstå) är förstås att bara definiera ett separat gränssnitt för strukturen:
export interface IModuleStructure {
icon: string;
label: string;
}
export interface Module {
name: string;
data: any;
structure: IModuleStructure;
}
export interface IDataModuleStructure extends IModuleStructure {
visible: boolean;
}
export interface DataModule extends Module {
structure: IDataModuleStructure;
}
export interface IUrlModuleStructure extends IModuleStructure {
url: string;
}
export interface UrlModule extends Module {
structure: IUrlModuleStructure;
}
let urlModule: UrlModule = {
name: "",
data: {},
structure: {
icon: '',
label: '',
url: ''
}
}
Redigera
Enligt @jcalz förslag, kan vi också göra modulgränssnittet generiskt, och skicka in det lämpliga strukturella gränssnittet:
export interface IModuleStructure {
icon: string;
label: string;
}
export interface Module<T extends IModuleStructure = IModuleStructure> {
name: string;
data: any;
structure: T;
}
export interface IDataModuleStructure extends IModuleStructure {
visible: boolean;
}
export interface DataModule extends Module<IDataModuleStructure> {
}
export interface IUrlModuleStructure extends IModuleStructure {
url: string;
}
export interface UrlModule extends Module<IUrlModuleStructure> {
}
let urlModule: UrlModule = { // We could also just use Module<IUrlModuleStructure>
name: "",
data: {},
structure: {
icon: '',
label: '',
url: ''
}
}
