Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No widening in strict null checking mode #8944

Merged
merged 3 commits into from
Jun 2, 2016
Merged

No widening in strict null checking mode #8944

merged 3 commits into from
Jun 2, 2016

Conversation

ahejlsberg
Copy link
Member

@ahejlsberg ahejlsberg commented Jun 2, 2016

This PR fixes #8878 and supercedes #8907. The PR implements the following three changes:

  • Empty array literals ([]) have type never[].
  • No widening of empty array literals in strict null checking mode. Since we already don't widen null and undefined literals in strict null checking mode, this means that the concept of widening now exists only for backwards compatibility with classic type checking mode.
  • In classic type checking mode we only widen the null and undefined types when they originate in null and undefined literals used in expressions. We don't widen null and undefined when they're used as type annotations. This is essentially a bug fix.

Since we expect --strictNullChecks to almost always be used in combination with --noImplicitAny, it seems pointless to widen the type of empty array literals from never[] to any[] since we'll immediately report an implicit any error following the widening. It seems better to preserve the more specific never[] type and require the programmer to add a type annotation if the array is actually going to be modified.

So, where the experience previously was

// Compile with --strictNullChecks and --noImplicitAny
var a = [];  // Error: Variable 'a' implicitly has an 'any[]' type
a.push(5);

the experience now becomes

// Compile with --strictNullChecks
var a = [];  // Type of a is never[]
a.push(5);   // Error: Argument of type 'number' is not assignable to parameter of type 'never'

Of course, when a type annotation is present there is no error:

// Compile with --strictNullChecks
var a: number[] = [];
a.push(5);

By altogether avoiding widening we solve some long standing issues in #531 and #1436.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 2, 2016

👍

@davidchambers
Copy link

This approach doesn't seem optimal: any[] is too permissive but never[] is too restrictive. The type of [] could be something like unknown[] which would allow the compiler to keep track of the fact that the inner type is still unconstrained. [].concat([]) would give [] of type unknown[] whereas both [].concat([1, 2, 3]) and [1, 2, 3].concat([]) would give [1, 2, 3] of type number[].

This approach works well for sanctuary-def but I don't know whether it is feasible for TypeScript.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Infer bottom type for type argument when passing empty array
4 participants