首页 文章

TypeScript:推断嵌套联合类型的类型

提问于
浏览
0

我正在使用TypeScript中的对象,它可能包含可以获取数据的延迟链接或数据本身 . 这就是为什么这些属性得到一个联合类型T |串 .

现在我想编写一个类型安全解析函数来解析返回嵌套类型的嵌套属性 .

type TypeOrString<T> = T | string;


interface A {
    propA: TypeOrString<B>;
}

interface B {
    propB: TypeOrString<any[]>;
}


function resolve<T, K1 extends keyof T, K2 extends keyof T[K1]>
(data: T | string, p1: K1, p2: K2): T[K1][K2] {
    return null;
}

let a:A;
let b:TypeOrString<any[]> = resolve(a, "propA", "propB");

//Error TS2345: Argument of type '"propB"' is not assignable 
//to parameter of type '"toString" | "valueOf"'.

但编译器给我一个错误,TS2345:类型'“propB”'的参数不能赋值给''toString类型的参数“的 Value ”' . 有没有机会从接口A的实例推断出propB的类型?

1 回答

  • 2

    你可以通过使用recursive mapped types模拟不仅是"data or a string",而且数据本身就是"data or a string"的事实来获得你正在寻找的东西 . 像这样:

    type DeepTypeOrString<T> = string | {
      [K in keyof T]: DeepTypeOrString<T[K]>
    }
    

    这主要为您提供了原始和普通对象类型的所需 . 数组是另一个故事,但是一旦conditional types功能登陆TypeScript 2.8,它就会被清除 .

    现在让我们根据您期望的实际数据定义 AB ,而不是"maybe string"版本:

    interface A  {
      propA: B
    }
    interface B {
      propB: any[]
    }
    

    你的 resolve() 函数与之前类似,只是 data 被声明为 DeepTypeOrString<T> 类型:

    declare function resolve<T, K1 extends keyof T, K2 extends keyof T[K1]>(
      data: DeepTypeOrString<T>, p1: K1, p2: K2
    ): T[K1][K2];
    

    现在当你调用 resolve() 时,你会看到你期望的推论:

    declare const a: DeepTypeOrString<A>;
    const ret = resolve(a, 'propA', 'propB') // ret is inferred as any[]
    

    希望有所帮助;祝好运!

相关问题