TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Order of ReadonlySet/ReadonlyMap in union causes differing key inference

Open jakebailey opened this issue 2 years ago • 1 comments

Bug Report

🔎 Search Terms

ReadonlyMap ReadonlySet key inference

🕗 Version & Regression Information

  • This is the behavior in every version I tried.

⏯ Playground Link

Playground Link

💻 Code

declare const map: Map<string, number>;


declare function forEachKey<K, T>(map: ReadonlySet<K> | ReadonlyMap<K, any>, callback: (key: K) => T | undefined): T | undefined;

forEachKey(map, (key) => {}) // Error passing "map", key type is wrong (number??)

forEachKey<string, void>(map, (key) => {}) // OK; no error, key type is string


// Now, flip the union order in the parameter's type.
declare function forEachKey2<K, T>(map: ReadonlyMap<K, any> | ReadonlySet<K>, callback: (key: K) => T | undefined): T | undefined;

forEachKey2(map, (key) => {}) // Okay?

forEachKey2<string, void>(map, (key) => {}) // Still okay.

🙁 Actual behavior

The order of the union appears to matter, breaking inference and erroring on valid code. Swapping the union order allows the code to compile.

🙂 Expected behavior

All of this should compile; the union ordering should not matter.

jakebailey avatar Jan 19 '23 21:01 jakebailey

:wave: Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript.


Issue body code block by @jakebailey

:x: Failed: -

  • Argument of type 'Map' is not assignable to parameter of type 'ReadonlySet | ReadonlyMap'. Type 'Map' is not assignable to type 'ReadonlyMap'. Types of property 'forEach' are incompatible. Type '(callbackfn: (value: number, key: string, map: Map) => void, thisArg?: any) => void' is not assignable to type '(callbackfn: (value: any, key: number, map: ReadonlyMap) => void, thisArg?: any) => void'. Types of parameters 'callbackfn' and 'callbackfn' are incompatible. Types of parameters 'key' and 'key' are incompatible. Type 'string' is not assignable to type 'number'.
Historical Information
Version Reproduction Outputs
4.8.2, 4.9.3, 5.0.2, 5.1.3, 5.2.2

:x: Failed: -

  • Argument of type 'Map' is not assignable to parameter of type 'ReadonlySet | ReadonlyMap'. Type 'Map' is not assignable to type 'ReadonlyMap'. Types of property 'forEach' are incompatible. Type '(callbackfn: (value: number, key: string, map: Map) => void, thisArg?: any) => void' is not assignable to type '(callbackfn: (value: any, key: number, map: ReadonlyMap) => void, thisArg?: any) => void'. Types of parameters 'callbackfn' and 'callbackfn' are incompatible. Types of parameters 'key' and 'key' are incompatible. Type 'string' is not assignable to type 'number'.

typescript-bot avatar Oct 26 '23 08:10 typescript-bot