TypeScript
TypeScript copied to clipboard
Order of ReadonlySet/ReadonlyMap in union causes differing key inference
Bug Report
🔎 Search Terms
ReadonlyMap ReadonlySet key inference
🕗 Version & Regression Information
- This is the behavior in every version I tried.
⏯ 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.
: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: -
|