I'm currently converting a large TypeScript codebase to strict null-checks. The codebase has many types with optional members:
interface MyInterface {
member1?: number;
member2?: string;
}
Furthermore, it uses a type Nullable<T> = T | null
, and has many return null
statements.
Now I'm facing many compiler errors which basically state that T | null
cannot be converted to T | undefined
, or vice versa, like in this example:
interface MyInterface {
member1?: number;
member2?: string;
}
const myFunction = () => {
return null;
}
const item: MyInterface = {};
item.member1 = myFunction(); // <== can't assign null to undefined
I love strict null-checking in TypeScript, but I have no use for the distinction between null
and undefined
. I can appreciate that there are some use cases where it makes sense to distinguish between null
and undefined
, but in this project, it really does not play an important part. These functions that return null
just return nothing - it does not matter whether it is null
or undefined
. Same goes for the optional members - they are either set to a value, or they are not.
I also prefer to not convert the member1?: number;
to member1: Nullable<number>;
, and to leave the return null
as they are
Can I disable the distinction between undefined
and null
, at least in TypeScript?
I'd better to wrote a comment, but since I want to show you some code example I leave it as answer.
If I were you, I would add some wrapper for all your interfaces with optional (weak) properties.
Here is an example of such wrapper:
type MapNullable<T> = {
[P in keyof T]: undefined extends T[P] ? (T[P] | null) : T[P]
}
interface MyInterface {
member1?: number;
member2?: string;
}
const myFunction = () => {
return null;
}
const item: MapNullable<MyInterface> = {};
item.member1 = myFunction(); // member1?: number | null | undefined
MapNullable
iterates through all properties. If property is optional, it just extend this property with one more type - null
, if property is not optional it leaves it as is.
I understand it is not the best solution, but at least it can help you with migration.
Once, you migrate, you can make your types more robust and get rid of MapNullable
interface.
MapNullable
is not the best name for type, but still better than Foo
or Bar
I agree with @jcalz, I can't imagine other way to handle undefined|null in other way
UPDATE
It looks like your code works without error in TS playground. Please see here
I have disabled strictNullChecks
. There is no error.
You should explicitly set return type of your function.
const myFunction = ():null => {
return null;
}
TS version: 4.0.2