-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[no-unnecessary-condition] False error on uninitialized variable #4513
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
Comments
The rule was written before optional chaining, and this "use before assigned" case was never added. It's very, very rare for people to write "use before assigned" variables, and even rarer that people use optional chaining with them. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
this has to be fixed in typescript, uninitialized variables should be reported by typechecker as let test: string;
function x () {
return test.length;
}
x(); this code is going to compile without error but, its actually going to produce runtime error |
We can use scope analysis to handle this. Simply put we can find the declaration, and if it's a variable with no intiailiser - then we can ignore the check. We already have similar code in the typescript-eslint/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts Lines 88 to 122 in dc58ff5
Relevant TS issue: microsoft/TypeScript#20221 |
that's good idea to use scopes for that there is only one issue with external variables, eg. exported from another file, but that should be even rarer case |
Across module boundaries there be Dragons. |
Note from #9206 that if (Math.random()) {
var x = 1;
}
if (x) {} |
I think the rule's behavior is correct in this case. And I think that IMO if you plan to read a variable in its uninitialized state, you should use |
Note also that the code which is proposed to be allowed in this issue is dangerous code that hides a type error from TS. TS assumes that let foo: string | undefined;
const setFoo = (): void => {
if (foo?.length < 1) {
// ~~~~~~~~~~~~~~~ TS ERROR 18048: 'foo.length' is possibly 'undefined'. 4:7 - 4:18
foo = 'foo';
}
}; Furthermore, if we remove the optional chain, it's not a type error (playground) let foo: string;
const setFoo = (): void => {
if (foo.length < 1) {
foo = 'foo';
}
}; Which cannot be the case for removing an unnecessary optional chain on an accurately typed variable. This is all to say, |
Fortunately, that's a TS use-before-define error 🙂, so I think we can avoid the mental strain of thinking about |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Since I wrote this, it was pointed out to me by @bradzacher that this rule autofixes this case, which can cause unsafe behavior. That's a very good point! I still believe strongly that the report is correct, but I agree that it's problematic to autofix this case. I believe the appropriate resolution would be to detect this case and downgrade the autofix to a suggestion. I'd like to open this issue to PRs for that resolution if there are no objections? |
filed #9565 to propose flagging the code in the issue report for failing to initialize |
Playground
tsconfig
Expected Result
Existence check on a possibly uninitialized variable should not trigger no-unnecessary-condition
For sure, the type might be extended to
let foo = string | undefined;
as workaround, but that actually looks a bit uncommon for a let definition, where not initializing might be intended.Actual Result
Unnecessary optional chain on a non-nullish value @typescript-eslint/no-unnecessary-condition
Versions
@typescript-eslint/eslint-plugin
5.10.0
@typescript-eslint/parser
5.10.0
TypeScript
4.5.5
ESLint
8.7.0
ts-node
10.4.0
The text was updated successfully, but these errors were encountered: