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

Wrong type inference for block scoped variables #42146

Closed
DavideCanton opened this issue Dec 29, 2020 · 4 comments
Closed

Wrong type inference for block scoped variables #42146

DavideCanton opened this issue Dec 29, 2020 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@DavideCanton
Copy link

DavideCanton commented Dec 29, 2020

TypeScript Version: 4.1.3

Search Terms: inference, variable, block, wrong

Expected behavior:
It should compile just fine.

Actual behavior:
Compilation error on row 16 due to wrong inference of variable.

Related Issues: not found

Code:

function setToTrue(func: (v: boolean) => void) {
    func(true);
}

function expect<T>(v: T): { toEqual: (t2: T) => void } {
    return {
        toEqual: v2 => {
            if (v !== v2) throw new Error('different values');
        }
    };
}

function foo() {
    let b: boolean | null = null;    
    setToTrue(x => b = x);
    expect(b).toEqual(true);
}
Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2017",
    "jsx": "React",
    "module": "ESNext"
  }
}

Playground Link: Provided

Type inference for variable "b" at row 14 is wrong, even if I specify explicitly "boolean | null". The compiler is unable to understand that b is effectively assigned immediately at line 15, and I find it to be correct, but it also infers that the actual type of the variable is just "null" and not "boolean | null" as I provided.
As a result, the code at line 16 (which I loosely borrowed from jasmine), does not compile, as the expect function is unable to get the property generic type instantiation, because T gets replaced with "null".

@MartinJohns
Copy link
Contributor

Duplicate of #9998.

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Dec 29, 2020
@DavideCanton
Copy link
Author

Sorry, I read the whole issue but I did not find which of the examples is covering my case.

Nobody in #9998 is complaining about block-scoped variables with explicit type being wrongly narrowed.

@MartinJohns
Copy link
Contributor

MartinJohns commented Dec 29, 2020

Type annotations for local variables are not considered if the variable doesn't get any other value assigned anywhere.

Some reason why foo is typed undefined and not number | undefined in this example:

const foo: number | undefined = undefined;
foo; // Hover over me.

This behavior is intentional, but causes problems with the issue from #9998.

Same issue as #40860. See also #8513.

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants