Typescript: strictNullChecks and nullable parameters with defaults

Created on 22 Feb 2017  ·  3Comments  ·  Source: microsoft/TypeScript

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.

Bug Fixed

Most helpful comment

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.

All 3 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kyasbal-1994 picture kyasbal-1994  ·  3Comments

jbondc picture jbondc  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

bgrieder picture bgrieder  ·  3Comments

Antony-Jones picture Antony-Jones  ·  3Comments