Typescript: ändra typ på objektets egenskaper och nästlade objekts egenskaper till en typ
Med detta exempel:
interface Event {
title:string;
description:string;
fromDate: Date;
toDate: Date;
location: {
name: string;
lat: number;
long: number;
}
}
Med en typ som PropertiesToString<Event> förväntar jag mig att returnera denna typ:
{
title:string;
description:string;
fromDate: string;
toDate: string;
location: {
name: string;
lat: string;
long: string;
}
}
Frågan är hur jag skapar typen PropertiesToString<T>?
Jag har lyckats skapa något som fungerar men inte för inbäddade objekt. Om jag har ett inbäddat objekt, istället för att ändra objektets egenskaper till sträng, sätter det objektet till en sträng.
Detta är min version som inte fungerar för nästlade objekt, eftersom den istället för att ändra typen på location properties to string, ändrar typen för location itself to string:
export type RequestBody<T> = {
[P in keyof T]: string;
};
Svar #1
typen ToString konverterar en given typ till string. PropertiesToString itererar över varje nyckel i den typ som skickas och ändrar dess typ till string med hjälp av ToString. Du kan lägga till andra specialfall som du vill hantera i ToString med hjälp av typens ternära operator.
interface Event1 {
title: string;
description: string;
fromDate: Date;
toDate: Date;
location: {
name: string;
lat: number;
long: number;
}
}
type ToString<T> = T extends Date
? string
: T extends object
? PropertiesToString<T>
: string
type PropertiesToString<T> = {
[K in keyof T]: ToString<T[K]>
}
type Generated = PropertiesToString<Event1>
type X = PropertiesToString<Event1['location']>
const x: Generated = {
title: 'lorem',
description: 'lorem',
fromDate: 'lorem',
toDate: 'lorem',
location: {
name: 'lorem',
lat: 'lorem',
long: 'lorem',
}
}
Lekplats
Svar #2
Du är faktiskt riktigt nära. Men det kommer att finnas några särskilda fall som du sannolikt måste hantera. I JS är många saker objekt, och du vill troligen inte att de alla bara ska bli strängar. Så du kommer antagligen att behöva förbättra detta med lite mer logik. Men i sin enklaste form
type RecursiveObject<T> = T extends Date ? never : T extends object ? T : never;
export type StringValues<TModel> = {
[Key in keyof TModel]: TModel[Key] extends RecursiveObject<TModel[Key]> ? StringValues<TModel[Key]> : string;
};
Lägg till eventuella specialfall (Array? Andra wrapper-typer?) som du behöver hantera i din kod. Så småningom kommer vi att få ’inte’-hantering i typer, och detta kommer att bli mycket enklare.
