【问题标题】:How to infer return type from parameter type in a generic function?如何从泛型函数中的参数类型推断返回类型?
【发布时间】:2019-02-17 12:54:26
【问题描述】:

这是一些条件类型的代码

class A {
    public a: number;
}

class B {
    public b: number;
}

type DataType = "a" | "b";

type TData<T extends DataType> =
    T extends "a" ? A :
    T extends "b" ? B :
    never;

现在我想使用条件类型作为从函数参数到其返回类型的链接。我试图以不同的方式实现这一目标,但没有结果:

function GetData<T extends DataType>(dataType: T): TData<T> {
    if (dataType == "a")
        return new A();
    else if (dataType == "b")
        return new B();
}

什么是正确的语法? TypeScript 2.8 可以吗?

更新

已经有一个opened issue on github 涵盖了我的示例。 所以目前的答案是“不,但将来可能”。

【问题讨论】:

    标签: typescript conditional-types typescript2.8


    【解决方案1】:

    你可以在这里使用函数重载:

    function GetData(dataType: "a"): A;
    function GetData(dataType: "b"): B;
    function GetData(dataType: DataType): A | B {
        if (dataType === "a")
            return new A();
        else if (dataType === "b")
            return new B();
    }
    
    const f = GetData('a');  // Inferred A
    const g = GetData('b');  // Inferred B
    

    【讨论】:

    • 当在实际代码中DataType 转换为一个大枚举时,这将变得很麻烦。
    【解决方案2】:

    三元运算符真的不适合泛型类型:

    type TriviallyA<T extends DataType> = 
          T extends any ? A : A;
    function GetData<T extends 'a' = 'a'>(dataType: T): TriviallyA<T> {
        return new A(); // Error: Type 'A' is not assignable to type 'TriviallyA<T>'
    }
    

    不过,泛型在属性查找方面确实表现出色,因此您可以定义一个接口来将字符串映射到特定类型,然后您可以使用keyof 和属性查找来充当TData

    interface DataTypeMapping {
        a: A;
        b: B;
    }
    type DataType = keyof DataTypeMapping;
    type TData<T extends DataType> = DataTypeMapping[T];
    
    function GetData<T extends DataType>(dataType: T): TData<T> {
        // now expected return type is A | B so this is valid!
        if (dataType === 'a') {
            return new A(); 
        } else if (dataType === 'b') {
            return new B();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-12
      • 1970-01-01
      • 2016-07-23
      • 2020-03-23
      • 2020-01-23
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多