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.

Povezani članci