Skip to content

Refinement in async functionΒ #61365

Closed
Closed
@philipnilsson

Description

@philipnilsson

πŸ”Ž Search Terms

"refinement async function"

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ. No entries matching "refinement" and nothing matching "async" or "await"

⏯ Playground Link

https://www.typescriptlang.org/play/?target=99&ts=3.8.3#code/IYZwngdgxgBAZgV2gFwJYHsIwEbAE4AUAlDAN4CwAUDDTHgKbIJ5YT0DuMACnugLaoQ9AgGsYAXgB8MIcgAqqPvXQJkogDQwAjAAYdRIgG4qAXypVQkWIhQYscdOmJkqtGABtGMZPRDIAXDAQCO7uMAA+ZDAAFvSh6IEA5OzoeO4AJokwJhJBIe7G1LRQmCDongB07ugA5gSJ0agAhIlE5kU0sgpKKmrOUi4dbt6+yLmkMXHVSSlpmWZDJm2UrrTA7MCoY7iERqs0JRBlldV1iT5+APyJmhfIy8MA9I90SBCoEDXesTAADrw1PDAPgyaLodggb7AMZ3GCCGAAAwmsXiM1SGSyJgROFUMDkYF+9AAylA8KhfmMPiU8AwoMh3GAYPsaM86PQ4B9fHCYeg8qFNEJ6AJPgy4TUIKkPl9kNFod96AxEpDgFh1psxuxGlBojA+MBGcB4pwZfQYKAQKhxUoIDyYsBfoT7Kg8H5mXdLhUUdVCgsqA4nHsVpQgA

πŸ’» Code

async function bar() {
    return new Promise(k => setTimeout(k, 100));
}

async function foo() {
    let test: null | { hello: 'world' } = null;
    console.log('hi!')

    setTimeout(() => {
        test = { hello: 'world'}
    })

    await bar();
    console.log('test?', test)
     // running the program shows that test is `{ hello: 'world' }` but TypeScript incorrectly 
     // refines it to null, seemingly ignoring that there's an await which may allow the assignment to happen first
    test?.hello;
}

foo();

πŸ™ Actual behavior

Getting a type error, where TypeScript refined the type of test to null

πŸ™‚ Expected behavior

The inferred type of test should be null | { hello: 'world' }

Additional information about the issue

There seems to be an issue where TypeScript ignores awaits (and yield/yield*) when doing refinement. It seems to me that at any point after an await you can no longer assume a refinement holds true.

I understand perhaps this may be a necessary tradeoff to avoid false negatives in many cases. However since there is an explicit assignment to a let declared variable in the same function it seems a bit funny. If this is a known limitation perhaps an entry in the FAQ could be added.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions