Type narrowing with assertions containing truthy literals
See original GitHub issueTypeScript Version: 4.2.0-dev.20201109
Search Terms:
type narrowing truthy
type narrowing assertion
conditional throw
Code
function test(foo?: number) {
if (!foo) throw new Error();
return foo.toFixed();
}
function testWithLiteralTrue(foo?: number) {
if (!foo && true) throw new Error();
return foo.toFixed();
}
function testWithTruthyLiteral(foo?: number) {
if (!foo && "str") throw new Error();
return foo.toFixed(); // Object is possibly 'undefined'.
}
Expected behavior:
In all three functions typescript would know foo
is a number after the assertion.
Actual behavior:
In the last example, testWithTruthyLiteral
, typescript complains foo
may be undefined
. This is the same behavior for all known truthy values except for literal true
.
Related Issues: https://github.com/microsoft/TypeScript/issues/29323
It sounds like from https://github.com/microsoft/TypeScript/issues/29323#issuecomment-454548280 that determining truthiness of expressions could lead to circular dependencies between compiler passes, but that literal true
has been special cased. This should be able to be extended to truthy literals without the circular dependency concern.
And for context, like others that have brought up similar issues, this stems from wanting a truthy token that can be used for a minification hook without affecting the types or code execution.
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (5 by maintainers)
Top GitHub Comments
It’s definitely kind of strange. The goal, like this comment, is to have assertions and other code that can be stripped out in a production build.
Here’s a contrived example:
Then, for a production build, you replace
"DEBUG_TOKEN"
withfalse
using something like@rollup/plugin-replace
so it gets eliminated with dead code removal:I find myself using this pattern in many cases rather than the non-null assertion operator so that it’s explicit why I expect the value to be non-null, and if for some reason it is null, you get a nice explanative error in development environments.
Besides non-null, we use this pattern for some assertion functions as well. One of them requires a recursive tree walk in a fairly hot codepath. It’s nice that we can provide these errors during development, but not pay the cost of the check when running in production.
It would be really nice if we didn’t have to sprinkle
!
all over or do things like this to get the types correct:or
Especially because tools like
terser
don’t remove this redundant assignment.Wait, this is just
since
''
is falsy