TypeScript Version: 2.2.1
It seems that TS 2.2.1 changed the behavior of nullable parameters (NOTE: null specifically, not undefined) with defaults when compiling with --strictNullChecks. Was this change intentional? It's a breaking change.
I imagine this is a consequence of #12033, but AFAICT affecting null was likely an unintentional side effect.
Code
type OptionalString = string | null | undefined;
function hasDefault(val: OptionalString = "") {
// TS 2.1.6, type of val is OptionalString
// TS 2.2.1, type of val is string
}
// TS 2.1.6, next line compiled fine
// TS 2.2.1, error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'.
hasDefault(null);
Expected behavior:
Type of val to be OptionalString (or string | null) and for null to be an accepted parameter.
Actual behavior:
Type of val is string and null is not accepted as an argument to the function.
Try it out in a JavaScript console.
function f(x = "") { return x.length; }
f("abc"); // 3
f(undefined); // 0
f(null); // ERROR
If you pass in null and it expects a string, you'll have runtime errors.
That's not the same case. In your example the parameter is not declared to accept null at all. Try this:
function f(x: string | null = "") {
return x.length; // Error: Object is possibly `null`
}
f("abc"); // 3
f(undefined); // 0
f(null);
That's how it should work. null should be accepted, but the function has to check for and handle it. However, note the different behavior between these two examples:
type T = string | null;
function f(x: T = "") {
return x.length; // Error here: `x` may be `null`
}
f(null);
Compare to this:
type T = string | null | undefined;
function f(x: T = "") {
return x.length;
}
f(null); // Error here: `null` is not assignable to parameter of type `string | undefined`
The first issue can be handled correctly, by checking for null within the function. The latter issue cannot be handled _at all_, because it incorrectly removes null from the type.
@sandersn @RyanCavanaugh Make sure #14498 also fixes this one.
Most helpful comment
That's not the same case. In your example the parameter is not declared to accept
nullat all. Try this:That's how it should work.
nullshould be accepted, but the function has to check for and handle it. However, note the different behavior between these two examples:Compare to this:
The first issue can be handled correctly, by checking for
nullwithin the function. The latter issue cannot be handled _at all_, because it incorrectly removesnullfrom the type.