typer - TypeScript: Betydelsen av `| [T]`-begränsning för kompileringstidkontroller av elementmedlemskap i arrayer
Jag vill skriva en funktion f som accepterar ett enda argument av typen A, där A måste vara en array som innehåller ett element av en viss typ T. För enkelhets skull, anta att T='ok' (singleton-typ av strängen 'ok').
Med hjälp av idén från detta svar erhöll jag följande preliminära lösning:
function f<
E,
A extends (ReadonlyArray<E> | [E]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
Som i svaret citerat ovan, fungerar det faktiskt.
Men jag kunde inte få någon mening av | [E]-delen, så jag bestämde mig för att kontrollera om jag kan ta bort den eller ersätta den med ännu en annan typ:
function f<
E,
X,
A extends (ReadonlyArray<E> | [X]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
Detta fungerar också, det vill säga det kan skilja mellan arrayer med eller utan elementet 'ok':
f(['a', 'b', 'ok', 'z']) // compiles, good
f(['a', 'b', 'z']) // does not compile, good
Mitt problem är att jag inte kan förstå varför det inte fungerar om jag tar bort [X]-delen. Det verkar helt orelaterat till allt som händer i koden:
- Ariteten av
[X]matchar inte ariteten hos tuplerna - Typen
Xär faktiskt inte bunden till något, den har inga gränser som innehåller varkenEellerAellerstringeller'ok'eller något annat.
Vad gör | [X] exakt?
Svar #1
Låt oss ta ett enkelt exempel:
function foo<T extends number[]>(t: T): T { return t }
foo([1, 2, 3]) // number[]
kommer att ha en arrayereturntyp som härleds.
function foo2<T extends number[] | [number]>(t: T): T { return t }
foo2([1, 2, 3]) // [number, number, number]
| [number] tvingar TypeScript att härleda en tuple istället för en array, utan att använda as const (en dold kompilatorregel, om man så vill).
Du kan till och med hålla numreriska literaler snäva genom att lägga till en typparameter R för arrayens element som utökar en primitiv typ:
function foo3<R extends number, T extends R[] | [R]>(t: T): T { return t }
foo3([1, 2, 3]) // [1, 2, 3]
Lekplats
