Reputation: 27200
For example, I have a function of the following form:
function wrap<T>(item: T): W<T> {
}
interface W<T> {
item: T;
}
Is it possible to write function (mapValues
), that will transform given object values by applying this wrap
function and return properly typed object? I understand how to write the actual function (lodash's _.mapValues
will work fine), but I don't know if it is possible to apply proper types.
Is it possible to write mapValues
function so the following will compile?
interface Before {
a: number;
b: string;
}
interface After {
a: W<number>;
b: W<string>;
}
let obj1: Before = { a: 1, b: "2" };
let obj2: After = mapValues(obj1);
function typecheck_number(arg: number) {}
function typecheck_string(arg: string) {}
typecheck_number(obj2.a.item);
typecheck_string(obj2.b.item);
Upvotes: 6
Views: 4273
Reputation: 27200
Here's one possible solution:
interface W<T> {
item: T;
}
function mapValues<T>(obj: T): {[K in keyof T]: W<T[K]>} {
// implementation
}
Unfortunately, similar recursive approach does not seem to be possible, but there is hope that it will be possible with type constraints from this proposal.
This link was very helpful in arriving to this solution: https://blog.mariusschulz.com/2016/05/31/type-queries-and-typeof-in-typescript
Upvotes: 4
Reputation: 3199
Yes, your types in the OP are correct. mapValues
only needs to be marked to return the type of After
.
Here is a TS playground that shows ur example working fine if mapValues
was to return a type of After
.
The properties of the mapped object are of type Wrap<T>
.
Upvotes: 0