typescript - Kartleggings-type av medlem av tuple


Jeg prøver å lage en kartlagt tuple som går ned til typen til et medlem:

export type Argument<T = unknown> = {
  value: T;
};

export type TypesOf<T extends Argument[]> = {[Index in keyof T]: T[Index]["value"]};

Så, TypesOf<[{value: number}, {value: string}]> bør gi [number, string].

Men jeg får denne feilen:

Type '"value"' cannot be used to index type 'T[Index]'.

REDIGER :

Bonusspørsmål etter å ha brukt @jcalz sin løsning:

const tuple = [{value: 1}, {value:"foo"}] as const;
type V = TypesOf<typeof tuple>;

Jeg får feil:

Type 'readonly [{ readonly value: 1; }, { readonly value: "foo"; }]' does not satisfy the constraint 'Argument<unknown>[]'.
  The type 'readonly [{ readonly value: 1; }, { readonly value: "foo"; }]' is 'readonly' and cannot be assigned to the mutable type 'Argument<unknown>[]'.

Svar #1

Implementeringen av TypesOf som du presenterer fungerer, i den forstand at TypesOf<[{value: number}, {value: string}]> faktisk evaluerer til [number, string]. Kartlagte typer på arrays og tuples resulterer i arrays og tuples.

Men det er et problem, rapportert i microsoft/TypeScript#27995 hvor kompilatoren ikke skjønner at innenfor den mappegte typen implementering {[I in keyof T]: ...T[I]...} vil I kun ende opp med å være de numerisk-lignende indeksene. Den tror at kanskje I vil være ting som "push" og "pop", og derfor kan ikke T[I] antas å være av typen Argument:

export type TypesOf<T extends Argument[]> =
    { [I in keyof T]: T[I]["value"] };
// -----------------> ~~~~~~~~~~~~~
// Type '"value"' cannot be used to index type 'T[I]'.

Antagelig er dette grunnen til at du stilte dette spørsmålet i utgangspunktet. GitHub-problemet er listet som en feil, men det har vært åpent lenge, og det er ikke klart om noe vil skje her.


I slike tilfeller pleier jeg å bruke Extract<T, U>-verktøystypen for å hjelpe med å overbevise kompilatoren om at en type kan tildeles en annen. Hvis du har typen T som du vet kan tildeles U, men kompilatoren ikke gjør det, kan du bruke Extract<T, U> i stedet for T. Når T spesifiseres senere, vil Extract<T, U> evaluere til kun T hvis du har rett om tildelbarheten. Og Extract<T, U> vil bli sett av kompilatoren som tildelbar til både T og U.

I vårt tilfelle vet vi at T[I] kan tilordnes til Argument, men kompilatoren gjør det ikke. Så følgende midlertidige løsning ved å bruke Extract<T[I], Argument> vil undertrykke kompilatorfeilen uten å påvirke outputen av TypesOf:

export type TypesOf<T extends Argument[]> =
    { [I in keyof T]: Extract<T[I], Argument>["value"] }; // no error

type Z = TypesOf<[{ value: number }, { value: string }]>;
// type Z = [number, string]

Ser bra ut!

Lenke til kode for lekeplass

Relaterte artikler