TypeScript: Can't compare property value other than 2, because of previously developed "if != 2 then error" code
Can’t compare property value other than 2, because of previously developed “if != 2 then error” code
if (vm.model.Id != '2')
throw new Error("...");
// some codes ...
if (vm.model.Id != '1')
throw new Error("...");
vm: { model : { Id : string; } }
"compilerOptions": {
"allowUnreachableCode": true,
"declaration": true,
"emitDecoratorMetadata": false,
"experimentalDecorators": true,
"module": "none",
"outFile": "test.js",
"target": "es5",
"sourceMap": true,
"lib": [ "dom", "es2015" ]
}
TypeScript 2.1.4 | Visual Studio 2015 Update 3
Actual behavior: Error: Operator ‘!=’ cannot be applied to types ‘“2”’ and ‘“1”’.
Is there any config to disable this behavior? I know why this is happening, but I’m not interested in this type of flow checking in typescript.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 4
- Comments: 19 (4 by maintainers)
We assume fields to be not changing “behind the scenes”. If they actually are, you’ll need to add a type assertion in the appropriate place to indicate otherwise.
@RyanCavanaugh @markboyall Do you see // some codes comment? Compiler can not and should not be responsible for such things! Let’s imaging that Id is a property that returns random string on its get. Compiler can detect this? The real codes is here:
https://github.com/bit-foundation/bit-framework/blob/master/Foundation/HtmlClient/Foundation.Test.HtmlClient/Implementations/Tests/radTests.ts
Line 58. Before the second if, I’m, calling await uiAutomation.formViewModel.setCurrent(); I promise you that vm.model.TestModel.Id will be ‘1’ after that. For now, I should write vm.model.TestModel.Id.ToString() instead of vm.model.TestModel.Id I can’t believe you’re saying this is working as intended. Is there any compiler on the planet other than typescript’s one doing this?
string is a primitive, is it not?
Take the following code, the comments are what intellisense tells me:
Why would the compiler assume that
namehas to be the string literal Fred in the second comparator? The compiler has no basis to say thatnameis Fred in my mind.Thanks to typescript’s definite-assignment-assertions you can handle this.
Following won’t gets compiled:
Following code gets compiled:
You’ve to use ! after vm.model.Id in first if
There’s discussion about whether this should be allowed or not here: https://github.com/Microsoft/TypeScript/issues/9998
Previously the type-narrowing was only applied in cases where it was guaranteed to be correct, it has now been expanded to other cases where it is assumed that function calls never mutate values. In lots of code this is fine, since it makes type guards easier to use, but it does feel like it is crossing a line, since there are now errors produced for correct code.
Why we’ve allowUnreachableCode flag, but we’ve no flag for this one? I can’t even build the application that was working like a charm before!
I can’t write valueHolder.value != 2 here! Why? you’ll see that this code works if you copy and paste it to https://www.typescriptlang.org/play/
The assumption here is that you’re not insane, and rather meant to write code that made sense. For example, it’s likely that if the compiler flags a warning here, you meant to write
&&instead of||, or===instead of!==, or one of your operands was incorrect.This logic has found multiple bugs in existing well-tested codebases. It’s a good trade-off vs just allowing nonsense code for the sake of allowing it.
Why? Since when are javascript objects assumed to be immutable? whats the point of
constthen?What “type assertion” are you referring to?
It’s not only not absurd, it’s completely correct if it’s immutable.
What is the type for
vm.model.Id? If it’sstringthen this is definitely a bug. The compiler should not coerce the property type based on a conditional check, that would be absurd.You know that it must be that thing, because if it wasn’t that thing, you threw an error. Since you didn’t leave the scope by throwing, it must be that thing.
The compiler is quite right to error, assuming that vm and vm.model are immutable. If you started mutating them, then it’s wrong…