I have something like { y: string; x?: number }, i need to get { y: string; x: undefined | number }. Is there a way to turn the first one into the second one via map types in typescript?
I have something like { y: string; x?: number }, i need to get { y: string; x: undefined | number }. Is there a way to turn the first one into the second one via map types in typescript?
You can get the type you want using mapped types. You can get the optional and required keys from a type as described here
type OptionalKeys<T> = { [K in keyof T]-?:
({} extends { [P in K]: T[K] } ? K : never)
}[keyof T]
type RequiredKeys<T> = { [K in keyof T]-?:
({} extends { [P in K]: T[K] } ? never : K)
}[keyof T]
type Id<T> = { [P in keyof T]: T[P]}
type OptionalToUndefined<T> = Id<{
[K in OptionalKeys<T>]-?: T[K] | undefined
} & {
[K in RequiredKeys<T>]-?: T[K]
}>
// { y: number | undefined; x: boolean; }
type Foo = OptionalToUndefined<{ x: boolean; y?: number }>
I ended up using this:
type EachNonOptional<T> = { [K in keyof T]-?: T[K]; }
type EachUndefinedOrNever<T> = { [K in keyof T]: undefined extends T[K] ? undefined : never };
type EachOptionalAsUndefined<T> = { [K in keyof EachNonOptional<T>]: EachNonOptional<T>[K] | EachUndefinedOrNever<T>[K] };
declare const x: EachOptionalAsUndefined<{ x?: number; y: string}>; // {x : number | undefined; x: string; }
or EVEN SIMPLIER:
type EachNonOptional<T> = { [K in keyof T]-?: T[K]; }
type EachOptionalAsUndefined<T> = { [K in keyof EachNonOptional<T>]: T[K] };