ToPrimitive
Challenge
Convert a property of type literal (label type) to a primitive type.
For example
type X = {
name: "Tom";
age: 30;
married: false;
addr: {
home: "123456";
phone: "13111111111";
};
};
type Expected = {
name: string;
age: number;
married: boolean;
addr: {
home: string;
phone: string;
};
};
type Todo = ToPrimitive<X>; // should be same as `Expected`
Solution
Die Lösung des Problems ist es, über alle Werte des Objekt-Typs zu iterieren. Falls ein Attribut ein Subtyp eines primitiven Typs ist (z.B. ist ein String-Literal ein Subtyp von String), dann geben wir einfach den primitiven Typ zurück. Für die geschachtelten Objekte rufen wir den Typ rekursiv auf, falls ein Array vorliegt, kann man diesen über einen Extra-Typ abfertigen (siehe ArrayToPrimitives)
// For this use-case only support string and number
type ArrayToPrimitives<T extends any[], Acc extends any[] = []> = T extends [
infer H,
...infer R
]
? H extends string
? ArrayToPrimitives<R, [...Acc, string]>
: ArrayToPrimitives<R, [...Acc, number]>
: Acc;
// Gibt den Basetyp eines Typs zuruck, z.B. fuer ein string literal den Typ 'string'
type ToPrimitive<T> = {
[key in keyof T]: T[key] extends string
? string
: T[key] extends number
? number
: T[key] extends any[]
? ArrayToPrimitives<T[key]>
: T[key] extends boolean
? boolean
: T[key] extends Record<string, any>
? ToPrimitive<T[key]>
: never;
};