Visual Studio Code - Hvordan kan jeg se den fullstendig utvidede kontrakten til en Typescript-type?
Hvis jeg har en samling av typer som ser litt slik ut:
type ValidValues = string | number | null
type ValidTypes = "text" | "time" | "unknown"
type Decorated = {
name?: string | null
type?: ValidTypes
value?: ValidValues
title: string
start: number
}
type Injected = {
extras: object
}
// overriding the types from Decorated
type Text = Decorated & Injected & {
name: string
type: "text"
value: string
}
Min faktiske kode har mer som skjer, men dette viser kjerneideen. Jeg vil ikke måtte stole på meg selv for å få forholdet mellom typene helt riktig. Jeg vil at verktøy skal vise meg hva typedefinisjonen for Text «evalueres» til, etter all typealgebraen.
Så for eksemplet ovenfor håper jeg at feltene spesifisert i Text vil overstyre de tidligere erklæringene gjort i Decorated-typen, og at utdataene fra en hypotetisk verktøytips skal vise meg noe som dette:
{
name: string
type: "text"
value: string
title: string
start: number
extras: object
}
Finnes det en enkel måte å få tak i denne informasjonen på?
Svar #1
Den raske informasjonen for en type som vises med IntelliSense etterlater ofte noe å ønske; du får vanligvis en enkelt fremstilling for en gitt type, som kan vise seg å være for kortfattet eller til og med for omstendelig for dine formål. Det finnes noen forslag for å gjøre det mer fleksibelt (f.eks. microsoft/TypeScript#25784 og microsoft/TypeScript#28508) slik at brukere kunne utvide/sammentrekke typedefinisjoner i sine IDEer. Men jeg vet ikke om de vil bli fulgt opp i nær eller til og med fjern fremtid, så la oss ikke vente på det.
Her er en typealias jeg noen ganger bruker for å prøve å utvide en type på den måten du snakker om:
// expands object types one level deep
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
// expands object types recursively
type ExpandRecursively<T> = T extends object
? T extends infer O ? { [K in keyof O]: ExpandRecursively<O[K]> } : never
: T;
De bruker betinget typeinferens for å "kopiere" en type T inn i en ny typevariabel O og deretter en identitetslignende kartlagt type som itererer gjennom de kopierte typens egenskaper.
Den betingede typeinferensen er konseptuelt en no-op, men den brukes for å distribuere unionstyper og for å tvinge kompilatoren til å evaluere «true»-grenen av den betingede (hvis du omdefinerer Expand<T> uten den, vil kompilatoren noen ganger bare produksere den mappede typen {[K in keyof RelevantType]: RelevantType[K]}, noe som ikke er det du ønsker å se).
Forskjellen mellom Expand og ExpandRecursively er om det bare skal vise egenskapstypene som de er (Expand), eller om det skal utvide egenskapstypene (ExpandRecursively). Det hjelper i det rekursive tilfellet å ikke prøve å grave ned i primitive typer, så derfor er T extends object-betingelsen inkludert.
OK, la oss se hva som skjer når vi bruker det på typen din. Vi trenger ikke ExpandRecursively i ditt tilfelle, men vi kan bruke det... det gir samme resultat:
type ExpandedText = Expand<Text>;
som, når vi holder musen over det i IDE-en (TypeScript Playground og VSCode uansett), vises som:
/* type ExpandedText = {
name: string;
type: "text";
value: string;
title: string;
start: number;
extras: object;
} */
som du ønsket.
Lenke til kode
Svar #2
Bare supplerer jcalz sitt svar med versjoner som fungerer med funksjoner.
De endrede hjelperne:
export type Expand<T> = T extends (...args: infer A) => infer R
? (...args: Expand<A>) => Expand<R>
: T extends infer O
? { [K in keyof O]: O[K] }
: never;
export type ExpandRecursively<T> = T extends (...args: infer A) => infer R
? (...args: ExpandRecursively<A>) => ExpandRecursively<R>
: T extends object
? T extends infer O
? { [K in keyof O]: ExpandRecursively<O[K]> }
: never
: T;
For å teste, legger jeg til en subobject-nøkkel til Text-typen, og legger til et funksjonsgrensesnitt:
type Text = Decorated &
Injected & {
name: string;
type: "text";
value: string;
subobject: Injected;
};
interface SomeFunction {
(...args: Text[]): Injected & { error: boolean };
}
Dette gir:
Objekter fungerer fortsatt bra:
Svar #3
Jeg fant ut at denne VS Code-utvidelsen fungerer perfekt for dette:
Pynt opp TypeScript: Bedre typeforhåndsvisninger
Den viser til og med dypt nestede typer når du holder musepekeren over dem.





