Skip to content

Unsafe Map overload spoils direct property access on parenthesized assignment expressionΒ #61506

@Andarist

Description

@Andarist

πŸ”Ž 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Domain: check: Type InferenceRelated to type inference performed during signature resolution or `infer` type resolutionHelp WantedYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some cases

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions