Typescript: razumijevanje unija i presjeka tipova
Pokušavam steći intuiciju o Uniji i Presjeku tipova u TypeScriptu, ali ne mogu shvatiti ovaj slučaj: Playground Link
interface A {
a: number;
}
interface B{
b: boolean;
}
type UnionCombinedType = A | B;
type IntersectionType = A & B;
const obj: UnionCombinedType = {
a: 6,
b: true,
}
const obj2: IntersectionType = {
a: 6,
b: true,
}
Zašto mi je dopušteno staviti obje vrijednosti u tip presjeka? Presjek između dvaju sučelja je prazan. Ako & čitam kao I, onda mi je jasno zašto mi dopušta dodavanje oba svojstva, ali tada bih | trebao čitati kao ILI i očekivao bih da mi dopušta dodati samo a ili b, ali ne oba.
Može li mi netko dati neku intuiciju o tim tipovima?
Odgovor #1
S obzirom na sljedeće:
interface A {
a: number;
c: number;
}
interface B{
b: boolean;
c: number;
}
Izraz unijskog tipa A | B može se dodijeliti ili A ili B. Mora imati svojstva iz A ili B (ili oba).
const oA: A | B = {
a: 6,
c: 6
}
const oB: A | B = {
b: true,
c: 6
}
const oC: A | B = {
a: 6,
b: true,
c: 6
}
Ali koje operacije ima tip poput A | B? Samo one koje pripadaju i A i B
oA.c = 1; // valid
Tip presjeka A & B, ako se može dodijeliti i A i B (i stoga mora imati svojstva i A i B).
const obj: A & B = {
a: 6,
b: true,
c: 1
}
Ažuriranje
Pitaš "zašto A i B u tvom primjeru mogu imati b svojstvo? nije dodjeljivo tipu A"
Ovo očito nije točno. Bilo koja vrsta koja ima sve osobine A može se dodijeliti A. Dodatne osobine ne škode:
const aAndExtraProp = {
a: 6,
c: 1,
d: 6
};
const ca0: A = aAndExtraProp;
Vjerojatno ste zbunjeni provjerama viška svojstava za literale objekata:
Objektni literali dobivaju poseban tretman i prolaze provjeru viška svojstava prilikom dodjeljivanja drugim varijablama ili prosljeđivanja kao argumenti. Ako objektni literal ima neka svojstva koja ‘ciljani tip’ nema, dobit ćete pogrešku:
const ca1: A = {
a: 6,
c: 1,
d: 6 //ERROR
};
Odgovor #2
Razmislite o vrednostima koje možete dodijeliti ovim tipovima, a ne o presjecanju i spajanju samih tipova.
type I = string & number;
type U = string | number;
const i: I = 5;
Ne uspijeva, želimo da i bude istovremeno i string i broj na neki način, ali to je nemoguće (I je ovdje nikad).
const u: U = 5;
u može biti niz ILI broj, tako da je u redu
Vraćajući se na tvoj primjer:
const obj2: IntersectionType = {
a: 6,
b: true,
}
Radi bez problema jer se obj2 presijeca s IntersectionType (ima obje svojstva a i b). TypeScript prolazi kroz svojstva u obj2 i utvrđuje da su sva potrebna svojstva IntersectionType prisutna.
I
const obj: UnionCombinedType = {
a: 6,
b: true,
}
Typescript gleda na obj... Ima li obj svojstva koja su potrebna u A? Da. To je dovoljno za TS.
Ako dodate svojstvo c oba objekta, TS će zakazati jer je to nepoznato svojstvo za oba tipa, ali to je druga priča.
