-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[no-unnecessary-type-assertion] This rule is different from the tslint rule 'no-unnecessary-type-assertion' #1310
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
I think the original tslint rule does it right. An non-null assertion is added just because the expression, at certain position, is believed to be non-null. And this has nothing to do with the assignment / return type. |
Have you got an example of where they differ? It's really hard to evaluate an issue like this with just the vague description. |
I add an example in the description above. |
Thanks. Looking at your example - I don't understand what's wrong with it. If you change the example slightly to: let x: string | undefined | null;
let y: string | undefined = x!; Then the rule will not report, because The point of the rule is to help you flag and remove code that doesn't do anything. In your example, the non-null assertion does literally nothing. I don't see the problem with using the extra information of the contextual receiving type to determine if the assertion is unnecessary. By using the receiving type, it also opens up the entire world of checking function arguments, react props, etc. declare const x: string | undefined;
declare function MyComponent(props: { prop: string | undefined }): ReactNode;
MyComponent({ prop: x! }); // non-null assertion is unnecessary
<MyComponent prop={x!} />; // non-null assertion is unnecessary Yes it is not exactly 1:1 with the tslint rule, but that's intentional. The TSLint rule is more relaxed, and thus misses the cases outlined above. I don't think the rule strays far enough away from the tslint rule to warrant being marked differently in the docs. It's only marginally more strict. Note that we do not attempt to have exact 1:1 compatibility with tslint rules for many reasons such as:
|
@bradzacher Can we reopen this issue for further discussion? This is not about compatibility with TSLint rules, but about being semantically correct. declare const x: string | undefined;
declare function MyComponent(props: { prop: string | undefined }): ReactNode;
makeXNonNull();
// And here we know x will be non-null, but the type system don't know about that,
// so we added a non-null assertion to hint the correct type of this expression.
MyComponent({ prop: x! }); In the modified example above, it is unnecessary to do non-null assertion to pass type checking, but it is semantically correct to do non-null assertion as we know The non-null assertion also provides a hint for other developers to quickly recognize the type of And the essential point behind is that, type assertion is the assertion to the type of the value being asserted, and it has nothing to do with the contextual receiving type. The idea "if the absence of type assertion won't make the compiler complain, then the type assertion is unnecessary" is simply not semantically correct. |
The name of the rule is pretty self-explanatory as to why it flag this usage. declare const x: string | undefined;
declare function MyComponent(props: { prop: string | undefined }): ReactNode;
makeXNonNull();
MyComponent({ prop: x! }); // no type error
MyComponent({ prop: x }); // no type error Considering there is no type error with or without the An important note is that this rule will do a similar check in the future for explicit casts (angle-bracket/as). It's just that those casts are a lot harder to handle, as they can use arbitrarily complex types, so I haven't gotten around to implementing it yet. typescript-eslint/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts Line 291 in 3ddf1a2
IMO it doesn't convey that meaning to the developer. The meaning it conveys when used like this: Everywhere I see people use the non-null operator, it's not in a place where there's been an explicit check. Why not? If there was an explicit check, you wouldn't need the assertion operator. Instead it's only used in places where the developer can say "it's reasonably safe to assume that the nullish type here shouldn't happen, and I don't think it's worthwhile to check for it". There's a really simple workaround for this as well, which the rule allows: declare const x: string | undefined;
declare function MyComponent(props: { prop: string | undefined }): ReactNode;
makeXNonNull();
// makeXNonNull will enforce that x is non-null, so we can assume the type is non-null for the rest of the block
const nonNullX = x!;
MyComponent({ prop: nonNullX }); Another approach, if you do not think the assertion is unnecessary, is to use an eslint disable comment. declare const x: string | undefined;
declare function MyComponent(props: { prop: string | undefined }): ReactNode;
makeXNonNull();
// This assertion is necessary to show that x has been previously asserted to be non-null, but the types were not updated as it was done in a different scope.
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
MyComponent({ prop: x! }); Also - just a nitpick - you shouldn't be using functions that imply such side-effects anyway. They are not typesafe for obvious reasons, and are a good way to introduce subtle bugs and type holes in your codebase. |
Uh oh!
There was an error while loading. Please reload this page.
The tslint rule 'no-unnecessary-type-assertion' reports an error only when the type assertions does not change the type of a variable. But this rule seems to report errors when the types of source variable and the receiver are different. These two rules are different, but the ROADMAP.md tells me these two rules are the same.
Example
Consider about the code above. There is no error when using tslint rule 'no-unnecessary-type-assertion', but there are errors when using '@typescript-eslint/no-unnecessary-type-assertion'.
Versions
@typescript-eslint/eslint-plugin
2.10.0
@typescript-eslint/parser
2.10.0
TypeScript
3.7.2
ESLint
6.7.2
node
12.13.0
npm
6.12.0
The text was updated successfully, but these errors were encountered: