You need to construct the final type as an intersection between an object type with the optional properties, and an object type containing the rest of the proeprties.
You can filter the undefined keys, using a similar approach to here. With the undefined
keys you can Pick
them from T
and make the optional using Partial
, to get the object type with the optional properties. On the other side you can use Omit
to omit the undefined
properties from T
type MyType = {
a: number | undefined
b: number
}
type UndefinedKeys<T> = {
[P in keyof T]: undefined extends T[P] ? P: never
}[keyof T]
type OptionalUndefined<T> = Partial<Pick<T, UndefinedKeys<T>>> & Omit<T, UndefinedKeys<T>>
type Id<T> = {} & { [P in keyof T] : T[P]}
type X = Id<OptionalUndefined<MyType>>
// type X = {
// a?: number | undefined;
// b: number;
// }
Playground Link
Note: Id
is used to flatten the resulting type, while this is not necessary it can be useful to make the type easier to read.