I have a interface defined as
interface IExample {
property1: string;
property2: number;
property3?: number;
property4?: string;
}
How do I make all optional properties accept null? I don't want to add null
to each optional property
I tried creating this type but this this does not work
type SetOptionalKeysNullable<T> = {
[K in keyof T]: T[K] extends undefined ? undefined | null : T[K];
};
The best way to detect optional properties is to use the (unsafe but convenient) assignability of a missing property to an optional property to a missing property. That is, {}
is assignable to {a?: string}
, but not to {a: string}
or to {a: string | undefined}
. Any checking that just looks at undefined
will end up being unable to distinguish optional properties from required properties that expect undefined
. So for each property K
in keyof T
, if {}
is assignable to Pick<T, K>
, then K
is optional in T
:
type SetOptionalKeysNullable<T> = {
[K in keyof T]: T[K] | ({} extends Pick<T, K> ? null : never)
};
Let's test it out:
interface IExample {
property1: string;
property2: number;
property3?: number;
property4?: string;
}
type ExOut = SetOptionalKeysNullable<IExample>;
/* type ExOut = {
property1: string;
property2: number;
property3?: number | null | undefined;
property4?: string | null | undefined;
} */
// none of these properties are optional
type Also = SetOptionalKeysNullable<{
a: string;
b: string | null;
c: string | undefined;
}>
type AlsoOut = SetOptionalKeysNullable<Also>;
/* type AlsoOut = {
a: string;
b: string | null;
c: string | undefined;
} */
Looks good. All of the optional properties get null
added to their domain, whereas nothing happens to any of the required properties.