Skip to content

Incorrect type inference of tuple when underlying array is extended #13941

Closed

Description

TypeScript Version: 2.1.5

Code

let x: [string, number];

x = ["hello", 10];
x[3] = 'hi';

let y = x[2];
if (y == null) {
    console.log('yes ever');
    y;
}

screen shot 2017-02-07 at 3 23 32 pm

$ node static/build/js/test.js 
yes ever

Expected behavior:

Before reading the docs, I would expect the type checker to find an error on line 4.

Given the feature set defined in the docs, I would expect the type at line 4 to be let y : undefined.

Actual behavior:

Type is incorrectly inferred as let y : never.

Activity

  1. changed the title [-]Incorrect type inference of tuple when it is extended[/-] [+]Incorrect type inference of tuple when underlying array is extended[/+] on Feb 7, 2017
  2. aluanhaddad commented on Feb 8, 2017

    @aluanhaddad
    Contributor

    Using --strictNullChecks and typescript@2.1.5, the type of y is string | number, outside of the if statement, and never inside of it.
    The inference of never is correct and expected because y is not not nullable, and therefore the block will never execute.
    With respect to the inferred type of the array element, I believe it is covered by the proposal in #6229

  3. anfedorov commented on Feb 8, 2017

    @anfedorov
    Author

    But the block does execute and the code compiles without warnings or errors, even with --strictNullChecks:

    code $ cat test.ts
    let x: [string, number];
    
    x = ["hello", 10];
    x[3] = 'hi';
    
    let y = x[2];
    if (y == null) {
        console.log('yes ever');
        y;
    }
    code $ tsc --strictNullChecks test.ts 
    code $ node test.js
    yes ever
    

    Thanks for the reference to the proposal — that is indeed a little closer to the behavior I would have expected.

  4. aluanhaddad commented on Feb 8, 2017

    @aluanhaddad
    Contributor

    Andrey Fedorov (@anfedorov) Ah, I see your point now. I misread it as y === null which would not be taken. It seems there may be a bug here, but I am not sure.

  5. anfedorov commented on Feb 8, 2017

    @anfedorov
    Author

    Yup, y is undefined, and the proposal you linked might be the most elegant fix.

  6. mhegazy commented on Apr 27, 2017

    @mhegazy
    Contributor

    unfortunately there is no way to do this correctly in the general case, e.g.: for (var z = 0, z<10, z++) x[z];. you can also find more details in #13778 on why the index signature intentionally, does not include undefined.

  7. anfedorov commented on Apr 28, 2017

    @anfedorov
    Author

    copying tuple behavior from Python seems like one way to handle it. i.e. x[3] = 'hi' could raise an error. another option is for x[3] = 'hi' to mutate the type of x to [string, number, undefined, string], fixing the error inside the if block.

    this seems to work fine in the playground: https://www.typescriptlang.org/play/index.html#src=let%20x%3A%20%5Bnumber%2C%20string%2C%20undefined%2C%20number%5D%3B%0D%0Ax%20%3D%20%5B1%2C%20'1'%2C%20undefined%2C%202%5D%3B%0D%0A%0D%0Ax%5B3%5D%20%3D%202%0D%0Ax%5B2%5D%20%3D%203%0D%0A

    regardless, x[z] just like x[prompt()] could be string | number | undefined?

  8. mhegazy commented on May 22, 2017

    @mhegazy
    Contributor

    Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

  9. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions