Recursive conditional types

后端 未结 3 847
走了就别回头了
走了就别回头了 2021-01-22 04:22

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:

3条回答
  •  南方客
    南方客 (楼主)
    2021-01-22 04:59

    So you need two things from the ConvertToTest type. One is that if T is a primitive type, then CovertToTest = 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 extends Primitive ? Test : {
        [K in keyof T]:
            T[K] extends (infer U)[] ? ConvertToTest[] :
            ConvertToTest;
    }
    

    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(obj: T): ConvertToTest;
    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.

提交回复
热议问题