Intuitive != expected != actual behaviour when combining string and symbol keys · Issue #26470 · microsoft/TypeScript (original) (raw)

TypeScript Version: 3.1.0-dev.20180813

Search Terms: string index inference, string key inference

Code

// function foo takes an 'options' object that can have: // (a) any number of string keys whose values are unary functions // (b) an optional 'directive' unique symbol key with a unrelated type const directive = Symbol('directive'); declare function foo<TArg, TRet, TDir>(options: {[x in string]: (arg: TArg) => TRet} // all the string keys are unary functions & {[directive]?: TDir} // there is an optional 'directive' symbol key ): void;

// CASE 1 // ~~~ERROR~~~ - ... prop 'addOne' incompatible with index signature // ... 'x' and 'arg' are incompatible // ... 'string' not assignable to 'number' let case1 = foo({ [directive]: (x: string) => 'str', addOne: (x: number) => x + 1, double: (x: number) => x + x, });

// CASE 2: identical to case 1 except for order of properties // Compiles OK - infers TArg = number, TRet = number, TDir = (x: string) => string let case2 = foo({ addOne: (x: number) => x + 1, double: (x: number) => x + x, [directive]: (x: string) => 'str', });

// CASE 3: identical to case 1 except for type of directive // Compiles OK - infers TArg = number, TRet = number, TDir = string let case3 = foo({ [directive]: 'str', addOne: (x: number) => x + 1, double: (x: number) => x + x, });

Intuitive expected behaviour:

All three cases compile without errors, with the string and symbol keys typed separately, since the type declaration clearly distinguishes the string keys from the symbol one.

Expected behavior according to #26257 (comment):

That comment suggests that all three cases should fail to compile, since the string index signature covers all symbol keys too, so any symbol key would have to conform to the string index signature, and they don't conform in any of the three cases in the code above.

Actual behavior:

Case 1 fails to compile, but Case 2 and 3 compile fine and in fact do type the string and symbol keys separately as intended by foo's definition.

Playground Link: here

Related Issues:
Taken directly from #26257 (comment). But the issue containing that comment is marked as 'working as intended' so I thought it would be better to open a new issue for this specific case.