set - Navngiving av TypeScript union- og snittyper


Jeg kan ikke forstå logikken bak begrepene intersection types og union types i TypeScript. Jeg tenker på grensesnitt (eller klasser) som mengder av egenskaper.

Den logiske konjunksjonsoperatoren & tilsvarer snitt i mengdelære, definert som:

Snittet av to mengder A og B er mengden som inneholder alle elementene i A som også tilhører B

I TypeScript bygges også en Intersection Type ved å bruke &-operatoren og defineres som:

Snitt-typen til grensesnittet Colorful og grensesnittet Circle er en ny type som har alle medlemmene til Colorful og Circle

Dette er det nøyaktige motsatte av hvordan snitt er definert i matematikk og mengdelære.

Jeg er sikker på at det finnes en annen måte å se det på, men jeg klarer ikke å finne den ut.

Svar #1

Her er en annen måte å tenke på det på. Tenk på fire sett: Blå ting, røde ting, store ting og små ting.

Hvis du skjærer settet av alle blå ting med alle små ting, ender du opp med foreningen av egenskapene - alt i settet har både den blå egenskapen og den lille egenskapen.

Men hvis du tok unionen av blå små ting og røde små ting, er det bare litenhets-egenskapen som er universell i det resulterende settet. Å snitte «blå små» med «røde små» gir «små».

Med andre ord, å ta unionen av verdidomenet gir et skjærende sett med egenskaper, og omvendt.

I bildeform:

Svar #2

Typen A | B refererer til objekter som er enten A eller B. Med andre ord, verdier av en slik type hentes fra unionen av verdier for A og verdier for B.

Typen A & B refererer til objekter som er både A og B. Med andre ord, verdier av slik type kommer fra snittet av verdier for A og verdier for B.

Navngivningen og semantikken er identiske i andre språk som C++.

Svar #3

Du må ikke tenke på typer som sett av objektattributter i dette tilfellet. Vi kan unngå forvirringen om hvordan union- og snitt-typer fungerer ved å se på skalarvariabler og deres sett med tillatte verdier (i stedet for objekter):

type A = 1 | 2
type B = 2 | 3
type I = A & B
type U = A | B

let a: A
let b: B
let i: I
let u: U

a = 1
a = 2
a = 3 // <- error

b = 1 // <- error
b = 2
b = 3

i = 1 // <- error
i = 2
i = 3 // <- error

u = 1
u = 2
u = 3

Her tilsvarer begrepene «union» og «snitt» nøyaktig settteoribegrepene når de brukes på mengdene av tillatte verdier.

Å anvende begrepet tillatte verdier (instanser) på objekttyper er litt mer utfordrende (fordi mengdelærens analogi ikke fungerer så godt):

type A = {
  x: number
  y: number
}

type B = {
  y: number
  z: number
}

type I = A & B
type U = A | B
  • En variabel av typen A kan holde objektinstanser med egenskapene x og y (og ingen andre egenskaper).
  • En variabel av typen B kan inneholde objektforekomster med egenskaper y og z (og ingen andre egenskaper).
  • I mengdelære er snittet av de to mengdene av objektinstanser ovenfor tomt. Imidlertid kan en variabel av snittype I inneholde objekter med egenskaper fra type A OG type B (dvs. x, y og z; derav symbolet &) som tilsvarer unionen av egenskapene til de to typene (derav forvirringen).
  • I mengdelære inkluderer unionen av de to settene med objektinstanser ovenfor ikke objekter med alle tre egenskapene. Imidlertid kan en variabel av unionstype U holde objekter med egenskapene til type A ELLER de av type B (logisk OR, ikke XOR, dvs. x og y, y og z, eller x, y og z; derfor symbolet |) noe som innebærer at snittet av egenskapene til de to typene (y i vårt eksempel) er garantert å være til stede (derav forvirringen).
let i: I
let u: U

i = { x: 1, y: 2 };         // <- error
i = { y: 2, z: 3 };         // <- error
i = { x: 1, y: 2, z: 3 };

u = { x: 1, y: 2 };
u = { y: 2, z: 3 };
u = { x: 1, y: 2, z: 3 };

Svar #4

Forvirringen her stammer sannsynligvis fra hvordan vi forestiller oss mengdene, nemlig at vi tenker på snittet/unionen som involverer medlemmene av typene i stedet for typene selv. Jeg satte sammen en grafikk som forhåpentligvis klargjør konseptet:

Relaterte artikler