Microsoft/TypeScript

Unsafe Map overload spoils direct property access on parenthesized assignment expression

Open

#61.506 geöffnet am 30. März 2025

Auf GitHub ansehen
 (2 Kommentare) (2 Reaktionen) (0 zugewiesene Personen)TypeScript (6.726 Forks)batch import
Domain: check: Type InferenceHelp WantedPossible Improvement

Repository-Metriken

Stars
 (48.455 Stars)
PR-Merge-Metriken
 (Durchschn. Merge 6T 17h) (9 gemergte PRs in 30 T)

Beschreibung

🔎 Search Terms

map overload any unknown unsafe weakmap set binary assignment lazy init

🕗 Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.0-dev.20250326#code/DYUwLgBAxghlAWIBcECyMAOAeAzmATgJYB2A5gDQQD2ARgFYhRgB8EAPhAK7EAmIAZiRA8A3ACgx-bk0JViEMCDwBGABQBrEAE8UeImQCUEAN5iI0OXgj4lnYJAC8EVbAQgIAfg9PiIAO5omKoGBgB0pOAa2gbi5gD0cebmAHoeZtbgnPjyNjh2YOIAvhJSxDJyCkpgAExROhB6JKRGpuauiJ7eEL4B6BjBsRbEVrn5EE7tIOGRmlox6QlJEKnpNmBZObb2RWJAA

💻 Code

let cache: Map<string, object> | undefined;

function test1(key: string) {
  const result = (cache ??= new Map()).get(key);
  //    ^? const result: any
  return result;
}

function test2(key: string) {
  cache ??= new Map();
  const result = cache.get(key);
  //    ^? const result: object | undefined
  return result;
}

🙁 Actual behavior

First result gets spoiled as any

🙂 Expected behavior

I'd expect both results to be object | undefined

Additional information about the issue

This bug reports an issue related to Map but, tbf, it's not unique to Map and a more general solution would have to be found to properly fix this. The problem is how checkBinaryLikeExpressionWorker create a union of left and right types here - without taking into consideration that the assignment target might already overlap with the right type. That union type gets reduced with UnionReduction.Subtype and .get gets read from it - instead of the assigned to reference on the left side.

Contributor Guide