microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.1k stars 12.5k forks source link

Non-null assertion operator whitespace allowances can create confusing conditional statements #60518

Open jaredmcateer opened 4 hours ago

jaredmcateer commented 4 hours ago

🔎 Search Terms

You can write a non-null assertion operator with whitespace after a variable name and no white space before certain keywords such as in and instanceof and the type checker doesn't fail but instead strips the operator creating the opposite condition as it appears.

To a someone not familiar with TypeScript/JavaScript key !in obj reads like if key not in obj . To them this might be if the tsc treated key !== 'a' as key == 'a'

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.0-dev.20241116#code/MYewdgzgLgBAZiEAuGBvAhgfhdATgSzAHMBfGAXjXRQHIAjdXGkgbgChRJYBrAUwE8KMGuhox0EGJ2js2+ODAAUfQQEJC8RAEo0bGFPAQQAG14A6YyCKKEIANoqAulvYk2chTcQx1XdGGBeEAUAeToAK15gKB1UPQNIE3NLayh+AAcghVsXNhIgA

💻 Code

const foo: {a?: string} = {a: 'bar'};
const key = 'a' as const;

if (key !in foo) {
  // non-null operator stripped and key exists in obj
  console.log(foo[key]);
}

if (foo !instanceof Object) {
  // non-null operator stripped and obj is Object
  console.log(typeof foo);
}

🙁 Actual behavior

The TSC stripped the non-null assertion, the operator should not be considered a non-null operator at all in this situation.

🙂 Expected behavior

I would expect a syntax error in this situation.

Additional information about the issue

This is a real problem not just hypothetical, I noticed a discussion started by a person learning typescript complaining about how their code was evaluating true regardless of the "negation operator" being used before the in keyword.

Image

bgenia commented 2 hours ago

Typescript-eslint has a rule for this