Reputation: 11791
I want to do something like this:
interface StateItem<T extends StateItemType>{
id: string;
values: {
[key in keyof T]: Provider<corresponding typeof T>
}
}
type Primitive = number | string | Position;
interface StateItemType {
[key: string] : Primitive;
}
interface Mover extends StateItemType {
center: Position;
speed: number;
vector: Position;
accruedVector: Position;
}
const mover : StateItem<Mover> = {
id: "123",
values: {
center: createRandomPosition(),
speed: createRandomNumber(),
vector: createRandomPosition(),
accruedVector: createRandomPosition(),
}
}
That is, given an interface T
which is a straightforward key:type map, when I create a StateItem<T>
an instances of that must have a values
object that contains all of those keys, and Provider<type>
instances.
How would I do this?
Upvotes: 0
Views: 764
Reputation: 74500
You can use the following type to access the property value type for each key in T
:
interface StateItem<T extends StateItemType>{
id: string;
values: {
[key in keyof T]: Provider<T[key]>>
}
}
The construct {[key in keyof T]: Provider<T[key]>}
is called a mapped type. It creates a new type, where each key in T
is mapped to a new property value type.
key
is a type variable and points to the currently used key, similar to a for...in
loop, where you can access each property successively with an index variable. key
can also be used in the property value type declaration part of the mapped type. By the way: you can rename key
as you like, often short names like P
or K
are used to distinguish those index type variables from real types.
Inside the mapped type, T[key]
would lookup the property value type for the currently accessed property key hold by key
variable inside T
(the typed to be mapped). So, something like this effectively is a NOOP:
type T1 = { foo: string; bar: number }
type T2 = {[K in keyof T1]: T1[K]} // not very interesting type...
Hope, it makes things a bit more clear!
Upvotes: 2