microsoft / TypeScript

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

Assignment "resets" already narrowed type #60521

Open hanwenguo opened 4 hours ago

hanwenguo commented 4 hours ago

🔎 Search Terms

"assignment operator" "type narrowing"

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.0-dev.20241116#code/GYVwdgxgLglg9mABAdzgJwNYGcAUAPALkXAzDmTAEoiso0YwBzRAbwChFEZhEcoBPAA4BTODzyIAvNMQAiWvSazKrDp0QSA1JLkLZAbjWc0wqCDRI8+xAHobiAIIQIwwVGEATIgHI83rliIYACGaGjknohQcIjeCgyM3moAvojCADZYwqrqiCZmFnIGKWzJbGygkLAIiFgAFnAg6R4OmXAA6ugYAEIgUAAicMJYAHJwUPhEJGQU1LV0CTlcPHxCouJSMvILSirsuRI6WnJ1GelwBrb2vv4MeXWBMIFxO4kANLF+XEjpDwGx03IYCSuXy5ks1jsiAAKmtEABRMLoHxfJ6IAD6JiyUHRURi3kBFBBiFSGSyS2MpnBRUMnDKySAA

💻 Code

function works(x: unknown): string {
  if (typeof x === "string") {
    x += "str";
    return x; // Accepted: 'x' is narrowed to 'string'
  } else {
    return "";
  }
}

function shouldAlsoWorkButDoesNot(x: unknown): string {
  if (typeof x === "string") {
    x = x + "hello"; // 'x' in rhs is 'string', 'x' in lhs is 'unknown'
    return x; // Type Error: 'x' is _reset_ to 'unknown'
  } else {
    return "";
  }
}

🙁 Actual behavior

There is two problems:

🙂 Expected behavior

x = x + ... follow the behave of +=, which is correct, in the above code example.

Additional information about the issue

Concerning inconsistency between += and x = x + ..., also see #60520.

jcalz commented 3 hours ago

Duplicate of #27706