-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Rule proposal: no-unsafe-type-assertion #7173
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 bet this would be a fascinating rule to figure out the details of... but it's blocked by the lack of a TypeScript assignability API: microsoft/TypeScript#9879. As much as I love a good Chuck Norris reference, not much point to discussing here until we have a TypeScript assignability API. 😞 Related:
|
Wow, I didn't know such an API didn't exist. I can't imagine how hard it must be to write rules without having a tool as basic as In the meantime, for my use case, I can just use a noop function that takes care of this. Something like: function safeAs<T>(x: T) {
return x;
} This allows you to do
Anyways, thanks for your quick response @JoshuaKGoldberg ! I leave the decision up to you as to whether it makes sense or not to keep this issue open. |
The |
Thanks @bradzacher ! The issue with a variable annotation is that it requires a separate statement. I believe the place where I use const bigObject = {
name: 'Random',
lastName: 'Guy',
age: 42,
} and then, in one test, do bigObject.age = '42'; // BE sometimes sends age as a string Since the objects are really large, I don't want to write the types myself. So, my "only" option is writing const bigObject = {
name: 'Random',
lastName: 'Guy',
age: 42 as string | number,
} To use a variable annotation I would need to declare |
I would love to see a eslint rule to disallow Does such a rule exist? I searched around but couldn't find it. Would the proposal in this issue cover that? Or would maintainers prefer I open a separate issue? |
#709 😢 blocked on microsoft/TypeScript#9879 |
Thansk @JoshuaKGoldberg I might take a custom linter into my own hands then. Do you foresee any issues if I wrote myself a custom eslint rule, which would simply look for the In this codebase specifically, I'm okay saying that "if the author really knows what they're doing and needs to use |
@TSMMark for disallowing |
Note Typescript 5.4 made
@JoshuaKGoldberg created a discussion stating that it will be usable in the next major: #7936 Does this mean a |
That should be right, yup! 🙌 |
🎉 For anyone that comes along after v8 is released, consider this "accepting PRs" (and please tag one of us to poke us so we can change the label) |
Now that v8 is released, per #7936, we can mark this issue as unblocked! 🚀 |
I should mention, if anyone's looking for inspiration, there's this implementation by a third-party plugin: https://github.com/danielnixon/eslint-plugin-total-functions/blob/master/src/rules/no-unsafe-type-assertion.ts Also, it'd be nice to properly document and teach alternatives to unsafe type-casts, here's the note I had in our internal linting docs: // It takes an advanced TypeScript user to fully make sense of this rule
/**
* It can sometimes be hard to make sense of this rule, but let's be strict!
* Tips:
* - Prefer coercion over assertion: e.g `String(value ?? '')` over `value as string | null`
* (this depends on your functional logic)
* - Try to assign to an explicitly typed variable and TypeScript will tell you about the type difference!
* ie: `const newValue: ExpectedType = unsafeValue`
* - If using TypeScript 4.9+, consider using the `satisfies` Operator:
* (https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/#the-satisfies-operator)
* `const newValue = {a: "A", b: 2} satisfies ExpectedType`
* - If using TypeScript 4.9+, consider using the `in` Operator to narrow unlisted properties:
* (https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/#unlisted-property-narrowing-with-the-in-operator)
* `if ("name" in unsafeValue && typeof unsafeValue.name === "string") ...`
* - Sometimes just casting as `Partial<>` is sufficient
* - Double check that you are not accidentally removing `null | undefined` from the type when casting:
* - `inputEvent.target as Partial<HTMLInputElement>` <-- Oops!
* - `event.target as Partial<HTMLInputElement> | null` <-- Ok!
*/ |
Before You File a Proposal Please Confirm You Have Done The Following...
My proposal is suitable for this project
Description
One of the hardest thing to explain to people not experienced in TS is when it's ok to use
as
. I default to tell people "don't useas
", and I constantly have to deal with that in code reviews. I'd love to have a rule that only allows type assertions that widen a type. For example,as unknown
is always totally ok.as string | number
is safe on astring
, but unsafe in astring | boolean
.This rule should only allow doing
x as Type
in the cases where the type ofx
is assignable totype
. So, the rule of thumb would be: ifconst a: Type = x
is fine, thenx as Type
is fine. Otherwise it's not.Fail Cases
Pass Cases
Additional Info
Here's a link to a TS playground with the passing and (proposed) failing cases.
The text was updated successfully, but these errors were encountered: