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
Bug: [no-unnecessary-condition] does not report an error for typeof/instanceof or "in" typeguards #7064
Comments
TypeScript types are a lower-bound, not an exact match. This means that the type So this does create a little bit of weirdness - for example if you check for a property that isn't in the type - this isn't an unnecessary check and can actually execute at runtime! However I do agree that we could detect redundant checks like "this property definitely exists in the type and is not optional". In the same vein - an So I don't think we should check Once more in the same vein - the result of a For example you may assign any non-nullish value to There are so many cases where the typeof can result in something you're not expecting which is why TS doesn't actually narrow the possible return strings for the operator. We won't be handling this case due to the complexity - if TS can't narrow it safely then we can't either. Relevant issue microsoft/TypeScript#46399 |
Before microsoft/TypeScript#46399 is fixed, it would still be valuable to detect the following case, right? declare const x: string/* possibly intersecting with other things */;
if (typeof x === "string"); |
We could potentially - but the thing I'm weary of (just like in that issue) is that we can handle I'm also not 100% if it should exist in this rule or not, it feels a little weird because:
Maybe a new rule like |
FWIW, if TS lands narrower types for |
The difficult thing is that we'd need ad version-specific logic to support both versions because we support older versions of TS. It's all doable - just a maintenance burden for us. |
Thanks for the elaborate answer! TS already reports an error when I assign a property that doesn't exist on it: Therefore the reverse isn't far fetched either? instanceof: typeof:
|
Because
TypeScript is structurally typed. class Something {
a = 2;
}
const obj: Something = { a: 1 }; // Works because the object satisfies the shape of Something
if (obj instanceof Something) {
console.log(obj);
} else {
console.log(obj);
} In this example, TS believes you go down the
The "simplest case" is exactly what we are discussing above: function bar(arg: { toString(): string }) {
if (typeof arg === "string") {
console.log(arg); // This is NOT redundant
}
}
bar("foo"); // Works |
Josh hit the nail on the head in all fronts! To further expand on the But there's also the case of functions that make it impossible to truly narrow - eg declare function acceptsName(arg: {name: string}): void;
acceptsName(function () {}); // no error!!!
declare function acceptsT(arg: {prop: string}): void;
acceptsT(function () {}); // correctly errors as expected
function foo() {}
namespace foo {
export const prop = "";
}
acceptsT(foo); // no error!!!
typeof foo === "function"
// foo is a function with properties! TS is a lot looser than people believe. If you're really strict with your code then you can be pretty safe with it but it's easy to be unsafe with it. For example the following is actually valid TS code that typechecks with no errors: const totallyAString1 = {} as string;
const totallyAString2 = {length: 1} as string; Which is one of the reasons that the TS team allows "unnecessary" checks without reporting and they don't narrow |
To summarize: what is/would be possible to do here? If I understood it correctly the |
Correct - However There's a bit of nuance to |
Before You File a Bug Report Please Confirm You Have Done The Following...
Playground Link
https://typescript-eslint.io/play/#ts=5.0.4&sourceType=module&code=PQKgBApgzgNglgOwC5gEQAEkE8AO0DGATnDkgLTTzLAID2ZArgghPtFAIaFZn60IATOEjj9UALjABtVBEKFahVAF0wIYAFgAUNjxgAtlgAquCGAC8YAN7awYAOQALCDBi17kqEmIIA5toBfAG5tbQAzJnwRfjAw2loACi5fSUMTPABKa1swODCwJMJfLKswYGAwJEcOJHsoWMQIUK07AOa7PIKnFzd7XIQwZJKyiqq4evGwQggBJgEOZHawNq0czoSAQgTu13d+waKM4fLKx0nJ6dnBBaQllZXwyOiBgCMuQpSwAFEANwhkEprfIffpeBZsWj5X7-JDHUZnCb1S5zG45Ow5B4tXLA3QQSEHXwWcyWey0F4AK1YtThp3OSJmKMWqyx9yAA&eslintrc=N4KABGBEBOCuA2BTAzpAXGYBfEWg&tsconfig=N4KABGBEDGD2C2AHAlgGwKYCcDyiAuysAdgM6QBcYoEEkJemy0eAcgK6qoDCAFutAGsylBm3TgwAXxCSgA
Repro Code
tsconfig
Expected Result
Errors in line 7, 11, 15, 21 and 25
Actual Result
Only error in line 7
Additional Info
No response
The text was updated successfully, but these errors were encountered: