typescript - Finns det ett sätt att få tuple-nycklar som nummer?


Tänk att jag har någon tuplet-typ:

type SomeTuple = ["a", "b", "c"];

Och nu vill jag på något sätt få dess nycklar som nummer:

type SomeTupleKeys<T = SomeTuple> = 0 | 1 | 2;

Jag har försökt använda keyof SomeTuple, men det returnerar

nummer | "0" | "1" | "2" | "längd" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | ... 14 till ... | "värden"

Jag har också försökt med en mer komplex lösning

type B = (SomeTuple extends infer T ? { [K in keyof T]: K extends keyof T ? K : never } : never)[number];

men den här ger strängar till mig:

"0" | "1" | "2"

Finns det ett sätt att få nummer utan att hårdkoda något?

Demo

Svar #1

Detta kan uppnås med rekursiva villkorstyper (tillagda i Typescript 4.1):

type TupleKeys<T extends ReadonlyArray<unknown>, Keys extends ReadonlyArray<number> = []> =
    T extends [infer _, ... infer R]
        ? TupleKeys<R, [R['length'], ...Keys]>
        : Keys[number];

type SomeTuple = ["a", "b", "c"];
type SomeTupleKeys = TupleKeys<SomeTuple>; // 0 | 2 | 1

Lekplats


En annan enklare lösning (fungerar med äldre versioner av TypeScript):

type TupleKeys<T extends Array<any>> = Exclude<Partial<T>['length'], T['length']>;

type SomeTuple = ["a", "b", "c"];
type SomeTupleKeys = TupleKeys<SomeTuple>; // 0 | 1 | 2

Här, genom att använda Partial får vi unionen av tupler av längd 0 eller 1 eller 2 eller 3, sedan exkluderar vi 3 (längden på den ursprungliga tuplen)

Lekplats