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
Extend the mapped type concept and syntax to allow mapping to a function type.
Use Cases
I am working on a project utilizing vuex. That library has good type definitions, but its store object exposes a very loosely typed API, out of necessity. Some of the most commonly used functions look like this:
The result is that interactions with the store have essentially no type checking. Since the store typically contains much of the core functionality of an app, it's unfortunate to lack type checking on all arguments to, and returns from that store.
I want to wrap and expose those APIs as more type-constrained functions that only accept known action & mutation names, and the correct payload type and return type associated with each. The ultimate goal is to define a single type representing each collection of actions or mutations, and from there, map to object types that can be used to type check the vuex module that is implementing those actions and mutations, and also map to function types that can be used to wrap vuex's dispatch and commit functions.
More generally, I think this same concept could be applied to many general-purpose tools that expose loosely typed APIs.
To the best of my understanding, the current mapped types syntax only supports mapping to object types.
...I want to use type mapping to map to a function type with overloads corresponding to each action in PersonActions, which would be equivalent to this:
To the best of my understanding, the mapped type syntax only supports mapping to object types.
type DispatchAction<T> = {
[P in keyof T]: T[P] extends (...args: any) => any
? (action: P, ...args: Parameters<T[P]>) => ReturnType<T[P]>
: never
};
Using the DispatchAction mapped type above with the PersonActions interface results in an object type with members setName and setAge:
type DispatchPersonAction = DispatchAction<PersonActions>;
// Equivalent to:
type DispatchPersonAction = {
setName: (action: 'setName', name: string) => Person;
setAge: (action: 'setAge', age: number) => Person;
}
Syntactically, I think this would require conceiving of an alternative way of defining a mapped type such that the P in keyof T portion doesn't result in a member name on the mapped type. I don't have an informed suggestion for this alternative syntax, but am hoping someone out there does!
Thanks!
Checklist
My suggestion meets these guidelines:
This wouldn't be a breaking change in existing TypeScript/JavaScript code
This wouldn't change the runtime behavior of existing JavaScript code
This could be implemented without emitting different JS based on the types of the expressions
This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
That's actually already possible, because intersection of function types is effectively the same as overloads and there's a UnionToIntersection hack (see #29594).
Wow @ark120202, thanks for the super quick response including a proof of concept with my examples! I just plugged it back into my project and it works like a charm.
Search Terms
mapped function types
Suggestion
Extend the mapped type concept and syntax to allow mapping to a function type.
Use Cases
I am working on a project utilizing vuex. That library has good type definitions, but its store object exposes a very loosely typed API, out of necessity. Some of the most commonly used functions look like this:
The result is that interactions with the store have essentially no type checking. Since the store typically contains much of the core functionality of an app, it's unfortunate to lack type checking on all arguments to, and returns from that store.
I want to wrap and expose those APIs as more type-constrained functions that only accept known action & mutation names, and the correct payload type and return type associated with each. The ultimate goal is to define a single type representing each collection of actions or mutations, and from there, map to object types that can be used to type check the vuex module that is implementing those actions and mutations, and also map to function types that can be used to wrap vuex's dispatch and commit functions.
More generally, I think this same concept could be applied to many general-purpose tools that expose loosely typed APIs.
To the best of my understanding, the current mapped types syntax only supports mapping to object types.
Examples
Starting with an object type like this:
...I want to use type mapping to map to a function type with overloads corresponding to each action in
PersonActions
, which would be equivalent to this:To the best of my understanding, the mapped type syntax only supports mapping to object types.
Using the
DispatchAction
mapped type above with thePersonActions
interface results in an object type with members setName and setAge:Syntactically, I think this would require conceiving of an alternative way of defining a mapped type such that the
P in keyof T
portion doesn't result in a member name on the mapped type. I don't have an informed suggestion for this alternative syntax, but am hoping someone out there does!Thanks!
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: