Repository navigation
Intuitive != expected != actual behaviour when combining string and symbol keys #26470
Description
Activity
Another small example from #26257:
If
{[x: string]: T}is intended to apply to all keys (i.e., strings, symbols and numbers), then shouldn't the following fail to compile, since the symbol key doesn't conform to the string index signature?const SYM = Symbol(); declare function foo(obj: {[x: string]: number}): void; foo({a: 1, [SYM]: 'sym'}); // Compiles fine
- changed the title
[-]Type inference problem when combining string and symbol keys[/-][+]Intuitive != expected != actual behaviour when combining string and symbol keys[/+]on Aug 20, 2018 Ryan Cavanaugh (@RyanCavanaugh) would you mind triaging this issue please?
Thanks Ryan Cavanaugh (@RyanCavanaugh). Can we clarify what the bug is here exactly? Is it that the string index seems to include symbol keys under certain conditions, or is it that the string index doesn't include symbol keys under certain conditions?
RyanCavanaugh commented
on Aug 20, 2018 MemberMore actionsI'm pretty unclear on which behavior is the desired one, which is why I was procrastinating on this one. In any case the property order really shouldn't matter, though.
I see. If it turns out that symbols must conform to string indexes, then I hope some consideration is given to how to declare things like
foowhere we want to type string and symbol keys separately.FWIW I can't think of any scenarios where you'd want a strongly-typed symbol property to be constrained by the string index. Symbol-keyed properties usually serve a very specific purpose (think of all the well-known symbols). The type of a symbol-keyed property is usually unrelated to the types of other keys in the same object. Certainly unrelated to string keys, and usually to other symbol-keyed properties too.
Hey Wesley Wigham (@weswigham), may I ask if there is something holding up the fix for this? Your PR has sat there for a couple of months now. Just wanting to know if this will be addressed by the time v3.2 comes out.
3.2 is a no at this point, given it's size, I'd guess. I'm still pushing for it, though. It's just hard to convince the relevant parties that it is both the correct fix (easy) and worth the change (hard). This issue and the others linked in the fix don't make the best case for a change of that size (not many upvotes, little obvious impact), so it's slow going.
OK. Well the PR has a much broader scope of changes that what this issue raises. Would a more limited change have more chance of making progress - eg just stop string indexes from constraining symbol keys? The other changes could possibly be approached later if there is demand.
So that's not really the issue here. The issue is that mapped types have a concept of mapping
symbolkeys, but no representation to map them into - so when we do inference, we end up discarding information (which is why the order matters). You need symbol index signatures to fix this.26 remaining items
- addedBugA bug in TypeScriptA bug in TypeScriptand removedFix AvailableA PR has been opened for this issueA PR has been opened for this issueInvestigatingIs in active investigationIs in active investigationSuggestionAn idea for TypeScriptAn idea for TypeScript
on Jan 23, 2020 - addedFix AvailableA PR has been opened for this issueA PR has been opened for this issue
on Nov 5, 2020 - locked as resolved and limited conversation to collaborators
on Oct 21, 2025
TypeScript Version: 3.1.0-dev.20180813
Search Terms: string index inference, string key inference
Code
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.