π 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.
π Search Terms
"refinement async function"
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play/?target=99&ts=3.8.3#code/IYZwngdgxgBAZgV2gFwJYHsIwEbAE4AUAlDAN4CwAUDDTHgKbIJ5YT0DuMACnugLaoQ9AgGsYAXgB8MIcgAqqPvXQJkogDQwAjAAYdRIgG4qAXypVQkWIhQYscdOmJkqtGABtGMZPRDIAXDAQCO7uMAA+ZDAAFvSh6IEA5OzoeO4AJokwJhJBIe7G1LRQmCDongB07ugA5gSJ0agAhIlE5kU0sgpKKmrOUi4dbt6+yLmkMXHVSSlpmWZDJm2UrrTA7MCoY7iERqs0JRBlldV1iT5+APyJmhfIy8MA9I90SBCoEDXesTAADrw1PDAPgyaLodggb7AMZ3GCCGAAAwmsXiM1SGSyJgROFUMDkYF+9AAylA8KhfmMPiU8AwoMh3GAYPsaM86PQ4B9fHCYeg8qFNEJ6AJPgy4TUIKkPl9kNFod96AxEpDgFh1psxuxGlBojA+MBGcB4pwZfQYKAQKhxUoIDyYsBfoT7Kg8H5mXdLhUUdVCgsqA4nHsVpQgA
π» Code
π Actual behavior
Getting a type error, where TypeScript refined the type of
testtonullπ Expected behavior
The inferred type of
testshould benull | { 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
letdeclared 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.