Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot map over intersection of string with string literal (e.g., "a" & string) #23651

Closed
jcalz opened this issue Apr 24, 2018 · 5 comments
Closed
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@jcalz
Copy link
Contributor

jcalz commented Apr 24, 2018

TypeScript Version: 2.9.0-dev.20180424 but reproducible as far back as I tested (2.7)

Search Terms: intersection, mapped, empty, string, literal

Code

type X = { [K in "a" & string]: 1 };

Expected behavior:
X should be equivalent to { a: 1 }.

Actual behavior:
X is {}.

Playground Link: link

Related Issues:
maybe #12114 for mapped types in general
maybe #23592 for making me notice this
maybe #16386 because I always think everything would be fixed by absorption
maybe #9410 although back then these things were treated as never everywhere


The recent #23592 change allowing mapping over number and symbol keys caused some of my existing code to break, and the obvious fix for some of them was to restrict those instances where I really expected strings from keyof T to (keyof T) & string. But that doesn't work. It looks like "a" & string gets treated like never inside of a mapped type key set, but like "a" everywhere else. Absorption would fix this, but barring that, maybe some less aggressive simplification inside mapped types?

Workaround: Since TS2.8 it is possible to use Extract<T, U> instead of T & U in some instances. In this case it can reduce the intersection before the mapping: type X = { [K in Extract<'a',string>]: 1 } is equivalent to { a: 1 } as expected.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 24, 2018

intersections are not aggressively reduced at the moment. there are some reduction that takes place when the intersection is used in a union (e.g. intersection of two literals go to never). in general we should be doing supertype reduction on intersections.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 24, 2018

we should add support for reducing string|number|enum & literal, enum & number

@mhegazy mhegazy added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Apr 24, 2018
@mhegazy
Copy link
Contributor

mhegazy commented Apr 24, 2018

Same issue as #9410

@jcalz
Copy link
Contributor Author

jcalz commented Apr 24, 2018

Is it the same issue? It seems related, but that one looks like it's fixed. Maybe whatever fixed that can be done inside mapped types as well?

@mhegazy
Copy link
Contributor

mhegazy commented Apr 28, 2018

Should be fiexed by #23751

@mhegazy mhegazy added Fixed A PR has been merged for this issue and removed In Discussion Not yet reached consensus labels Apr 28, 2018
@mhegazy mhegazy closed this as completed Apr 28, 2018
@mhegazy mhegazy added this to the TypeScript 2.9 milestone Apr 28, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants