When applying the DeepPartial
generic type from utility-types
to Typescript type I notice that the type of all properties is automatically expanded to include undefined
. I.e. a property that previous was of type T
now become T | undefined
.
E.g. the following code fails typechecking:
import { DeepPartial } from 'utility-types';
type A = { a1: number, a2: number};
type B = DeepPartial<A>;
const b: B = { a1: null };
Typescript playground is here.
I get it that this is what plain old Partial
does as well. But is there a deeper reason why | undefined
was chosen (in both cases) as opposed, e.g. to: | null
or | null | undefined
and is there a way I can customize the DeepPartial
generic type so as to generate property types with | null
instead?
The purpose of Partial<T>
is to transform a type like {x: number, y: string}
into a type where the properties are all optional, like {x?: number, y?: string}
. In this case the types of the properties are number | undefined
and string | undefined
because ?
means the property is allowed to be missing, and undefined
is what you get when accessing a missing property.
To get null
instead of undefined
, you can just take the source code for DeepPartial and adjust it:
type DeepNullable<T> = T extends Function
? T
: T extends Array<infer U>
? _DeepNullableArray<U>
: T extends object
? _DeepNullableObject<T>
: T | null;
interface _DeepNullableArray<T> extends Array<DeepNullable<T>> {}
type _DeepNullableObject<T> = { [P in keyof T]: DeepNullable<T[P]> | null };
Demo:
type Foo = {
foo: number,
bar: {
baz: Array<{ quz: string }>
qux: boolean
}
}
// test has no type errors
let test: DeepNullable<Foo> = {
foo: null,
bar: {
baz: [{quz: null}, {quz: null}],
qux: null
}
}