crypto-community-bestedingen-1-miljoen-om-elon-musk-geïnspireerde-token-floki-inu.jpg

Typescript type vernauwing

Bronknooppunt: 1857482

Vaak moeten we onderscheid kunnen maken tussen Typescript-interfaces die enkele eigenschappen gemeen hebben. Neem het volgende voorbeeld:

interface Vehicle { weight: number; wheels?: number; class?: 'A' | '1' | '2' | '3';
}

In onze applicatie hebben we verschillende voertuigen. Voor vrachtwagens willen we bijvoorbeeld het gewicht en het aantal wielen bijhouden. Andere voertuigen (zoals jachten) hebben echter geen wielen, maar hebben andere attributen die we willen weten, zoals bijvoorbeeld hun klasse, wat een string is die de waarden 'A', '1', '2' of '3' kan aannemen. .

We zouden kunnen denken dat een goede configuratie er als volgt uit kan zien:

interface Truck { weight: number; wheels: number;
} interface Yatch { weight: number; class: 'A' | '1' | '2' | '3';
} export type Vehicle = Truck | Yatch;

Met deze opstelling zullen we echter een probleem hebben bij het proberen te gebruiken Vehicle voorwerpen:

Zoals we kunnen zien, kan Typescript niet beslissen of het invoerobject a is Truck of Yatch, en het genereert de volgende fout:

Property 'wheels' does not exist on type 'Yatch'

Hoe kunnen we het type van het object verfijnen? Er zijn minimaal 3 alternatieven:

1. Maak een nieuwe type eigenschap op elk van de interfaces

interface Truck { weight: number; wheels: number; type: 'truck';
} interface Yatch { weight: number; class: 'A' | '1' | '2' | '3'; type: 'yatch';
} export type Vehicle = Truck | Yatch;

Dit staat bekend als gediscrimineerde vakbonden in typoscript. Deze oplossing zou het meest geschikt zijn als onze interfaces al over de type attribuut vooraf.

Tijdens gebruik Vehicle objecten, nu kunnen we een schakelkast gebruiken om beide interfaces te onderscheiden:

Als we klassen gebruiken in plaats van interfaces voor onze typen, levert de volgende alternatieve syntaxis exact hetzelfde resultaat op:

class Truck { weight: number; wheels: number; readonly type = 'truck';
} class Yatch { weight: number; class: 'A' | '1' | '2' | '3'; readonly type = 'yatch';
} export type Vehicle = Truck | Yatch;

2. Gebruik typebeschermers

Type bewakers zijn functies die helpen bij het verkleinen van het type.

interface Truck { weight: number; wheels: number;
} interface Yatch { weight: number; class: 'A' | '1' | '2' | '3';
} export type Vehicle = Truck | Yatch; export function isTruck(arg: any): arg is Truck { return !!arg.weight && !!arg.wheels;
} export function isYatch(arg: any): arg is Yatch { return !!arg.weight && !!arg.class;
}

If isTruck(object) Retourneren true, betekent dit dat ons object inderdaad a is Truck. We kunnen deze functies overal in onze applicatie importeren en gebruiken:

Er is echter een klein probleem met deze opstelling: we kunnen nog steeds bouwen Vehicle voorwerpen die dat niet zijn Truck noch Yatch:

3. Gebruik ‘nooit’

Om dit laatste probleem op te lossen kunnen we gebruik maken van de never type, geïntroduceerd in Typescript 2.0. Als een interface de eigenschap type heeft never, dan kan die eigenschap niet worden gedefinieerd voor enig object dat op die interface volgt.

interface Truck { weight: number; wheels: number; class?: never;
} interface Yatch { weight: number; wheels?: never; class: 'A' | '1' | '2' | '3';
} export type Vehicle = Truck | Yatch;

Type guards werken precies zoals voorheen, maar nu kunnen we geen creaties meer maken Vehicle objecten die tegelijkertijd beide hebben wheels en class eigendommen:

Zoals we kunnen zien, verkrijgen we de volgende fout:

Type 'number' is not assignable to type 'never'

Bekijk de Spaanse versie van dit bericht op mijn blog cibetrucos.com

Bron: https://www.codementor.io/davidsilvasanmartin/typescript-discriminated-unions-1jhqp24mvx

Tijdstempel:

Meer van Codementor-gemeenschap