You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Mapped types enumerating keys in string behave poorly #22509
Here I expect string to behave as if it were the union of all possible string literal types. The present semantics are identical to a string indexer. IMO if we don't want map types K in string to do anything interesting, then the syntax should be an error and we should require people to write the indexer.
For what it's worth, ultimately I would love to type Allen's Apparatus for Method Extraction, roughly typed below:
I would probably work towards putting a constraint on T such that you get a red squiggle if you pass an object without the proper method to extract, but hopefully this serves as a useful example.
changed the title [-]Map types enumerating keys in `string` behave poorly[/-][+]Mapped types enumerating keys in `string` behave poorly[/+]on Mar 13, 2018
Jack Williams (@jack-williams) Sort of. It might mean that string index signatures would need to boil down to something similar to the following call signatures
EDIT: The syntax I've picked is completely misleading as it just defines a method called get. The syntax should probably be something different like get [K: string] (): T.
I'm afraid my understanding of numeric indexers probably has many holes. Am I correct in thinking that the stickiness with number-like strings mostly arises when you have named properties? E.g.
interfaceNumGetSet<T>{get<Kextendsnumber>(): Tset<Kextendsnumber>(v: T): void;"10": number;// How do we detect that this is inconsistent? }
Although, I don't know if you want want to replace numeric indexers necessarily. Perhaps it could just be limited to types that extend string?
This really is a request to add compiler support for ECMAScript proxy objects, i.e. compiler knowledge of the relationship between property access operations and the get and set proxy methods. It is simply not possible to model that with our current type system features (because nothing allows you to capture the literal type corresponding to the property name in a property access). This new feature would likely also include support for mapping call operations onto the apply and construct methods.
I do think this is entirely orthogonal to mapped types, and I think the current behavior of mapping over type string is correct and consistent.
It's like a type with an index signature but special properties don't have to be assignable to the index type.
I agree this is somewhat useful for the get trap side of proxies. I believe exotic get behavior is more common than exotic call behavior so this may even be a reasonable starting point for "proxy support".
I think I contest consistent, but I admit this is based on a surface-level understanding. I'll try to illustrate. Given the type { [K in 'a' | 'b']: K }, it has three important behaviors:
A property is created for each member of in's RHS.
The type of that property corresponds to the property name
All properties are are required
However, { [K in string]: K }, a very similar construct, seems to only exhibit the first behavior but not the second or third.
I have a use case now where this would be a helpful feature:
typeItem<Textendsstring>={id: T;};exporttypeItemMap={[idinstring]: Item<id>;};constmap: ItemMap={};constitem=map['someid'];// type is Item<string> when it would be nice to be Item<'someid'>
I would like a solution to this as well. I'm specifically interested in typing a Proxy for use in a tRPC-like library that requires accurate types to share types in the server and client, but Jacob Eggers (@eggers) has another good use case, and I don't think something special for Proxy is necessary.
Maybe this is a little contrived but you could assert an id field matches the key in the map:
Activity
RyanCavanaugh commentedon Mar 13, 2018
Ping Anders Hejlsberg (@ahejlsberg)
[-]Map types enumerating keys in `string` behave poorly[/-][+]Mapped types enumerating keys in `string` behave poorly[/+]jack-williams commentedon Mar 13, 2018
That would be very cool! I guess it would be kind of like specifying a parameterised getter? (If that were a thing).
DanielRosenwasser commentedon Mar 13, 2018
Jack Williams (@jack-williams) Sort of. It might mean that string index signatures would need to boil down to something similar to the following call signatures
But then what about numeric index signatures? You'd need a way to encode number-like strings:
jack-williams commentedon Mar 13, 2018
Daniel Rosenwasser (@DanielRosenwasser) Yes I guess you would want these to be equivalent:
EDIT: The syntax I've picked is completely misleading as it just defines a method called
get. The syntax should probably be something different likeget [K: string] (): T.I'm afraid my understanding of numeric indexers probably has many holes. Am I correct in thinking that the stickiness with number-like strings mostly arises when you have named properties? E.g.
Although, I don't know if you want want to replace numeric indexers necessarily. Perhaps it could just be limited to types that extend
string?ahejlsberg commentedon Mar 14, 2018
This really is a request to add compiler support for ECMAScript proxy objects, i.e. compiler knowledge of the relationship between property access operations and the
getandsetproxy methods. It is simply not possible to model that with our current type system features (because nothing allows you to capture the literal type corresponding to the property name in a property access). This new feature would likely also include support for mapping call operations onto theapplyandconstructmethods.I do think this is entirely orthogonal to mapped types, and I think the current behavior of mapping over type
stringis correct and consistent.bterlson commentedon Mar 14, 2018
Anders Hejlsberg (@ahejlsberg) I think proxies are a bit of a red herring here. For example, something like the following is fairly common I think?
It's like a type with an index signature but special properties don't have to be assignable to the index type.
I agree this is somewhat useful for the get trap side of proxies. I believe exotic get behavior is more common than exotic call behavior so this may even be a reasonable starting point for "proxy support".
I think I contest consistent, but I admit this is based on a surface-level understanding. I'll try to illustrate. Given the type
{ [K in 'a' | 'b']: K }, it has three important behaviors:in's RHS.However,
{ [K in string]: K }, a very similar construct, seems to only exhibit the first behavior but not the second or third.RyanCavanaugh commentedon Jun 24, 2021
This doesn't seem to be a common request and I haven't seen other problems that would be solved by addressing this
DanielRosenwasser commentedon Oct 7, 2021
Keywords to find this later: generic index signature type parameters on index signature proxy Brian Terlson (@bterlson)
eggers commentedon Aug 29, 2022
I have a use case now where this would be a helpful feature:
tlrobinson commentedon Jan 29, 2023
I would like a solution to this as well. I'm specifically interested in typing a
Proxyfor use in a tRPC-like library that requires accurate types to share types in the server and client, but Jacob Eggers (@eggers) has another good use case, and I don't think something special forProxyis necessary.Maybe this is a little contrived but you could assert an
idfield matches the key in the map:If you're able to enumerate the possible keys (I'm not in my real use case) this does work as expected: