I'd like to map an object recursively so that the primitive values in the object are converted to some other type.
For example, I'd like an object like this:
const before = { a: { c: '' }, b: [ '', { d: '' } ] }
to become this:
const after = { a: { c: Test }, b: [ Test, { d: Test } ] }
I'm also assuming that values won't be Date, Symbol, or null/void. Just JSON serializable types like string, numbers, etc. (except null)
Here's what I tried:
type ConvertToTest<T> = {
[P in keyof T]: T[P] extends any[]
? ConvertToTest<T[P]>
: T[P] extends {}
? ConvertToTest<T[P]>
: Test;
}
function convert<T>(o: T): ConvertToTest<T> {
// ...
}
This is using the conditional types introduced in Typescript 2.8.
const after = convert(before) results in after.a.c with string type completions in the editor for c, instead of completions for Test.
How do I rewrite type ConvertToTest<T> to convince Typescript that after.a.c is of type Test?
EDIT: Here's a Typescript Playground link illustrating the above.
So you need two things from the ConvertToTest<T> type. One is that if T is a primitive type, then CovertToTest<T> = Test. The other is that if T isn't primitive, you want to keep the same keys but convert their values.
To do that, I'd just add the first case as one part of a conditional type, and then have the other branch use a recursive mapped type:
type Primitive = string | number | boolean | null | undefined;
type ConvertToTest<T> = T extends Primitive ? Test : {
[K in keyof T]:
T[K] extends (infer U)[] ? ConvertToTest<U>[] :
ConvertToTest<T[K]>;
}
Using that, you can then use it like so:
// For example. Replace with whatever your actual type is.
type test = {
foo(): string;
}
declare function convertToTest<T>(obj: T): ConvertToTest<T>;
const test = convertToTest({ a: "", b: { c: true, primArr: [1, ""], objArr: [{inner: ""}] } });
test.a.foo(); // OK
test.b.c.foo(); // OK
test.b.primArr[0].foo() // OK
test.b.objArr[0].inner.foo() // OK
This is a nice way to do it since it will work for objects of any depth, and will properly handle converting the elements of an array type as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With