为什么使用条件运算符会导致交集类型?

时间:2019-09-04 08:13:42

标签: typescript

我正在尝试创建一个泛型函数,该函数根据其参数的类型有条件地返回值,但是我一直在尝试实现返回类型。

假设类型为 USA USA USA USA UK UK Date Alabama Alaska Kansas Maryland London Edinburgh ----------------------------------------------------------------------- 01/01/2019 1 2 3 4 5 6 02/01/2019 7 8 9 10 11 12 03/01/2019 13 14 15 16 17 18

Basket

现在,如果我想根据传递给函数的参数有条件地返回“ banana”或“ tomato”,则无法编译它:

type Basket = {
    Fruit: 'banana',
    Veggie: 'tomato'
}

现在,当我在传递正确的通用参数后实例化此参数时,我得到了我所期望的类型,但是它无法编译

const f1 = <T extends keyof Basket>(t: T): T extends 'Fruit'? 'banana': 'tomato' => {
    if (t == 'Fruit') {
        return 'banana' //Error on this line - doesn't compile -- Type '"banana"' is not assignable to type '"banana" & "tomato"
    } else {
        return  'tomato' //Error on this line - doesn't compile -- Type '"tomato"' is not assignable to type '"banana" & "tomato"
    }
}

但是,如果我不使用泛型,我会得到一个像这样的求和类型

const doesntCompile: 'banana' = f1<'Fruit'>('') //type: 'banana', which is what I want ... but this doesn't compile due to the error above.

现在它可以正常编译,但是我失去了类型安全性的好处。

如何在保留泛型的同时使该示例正常工作?任何帮助深表感谢。

1 个答案:

答案 0 :(得分:2)

关于您的问题,它来自延迟的条件类型。查看打字稿文档:https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types。 (将条件类型的搜索推迟到页面中的正确位置。)

最简单的解决方案是使用一个更宽松的单独实现签名,同时将公共签名保留为对调用者更有利的条件类型:

type Basket = {
    Fruit: 'banana',
    Veggie: 'tomato'
}

function f3 <T extends keyof Basket>(t: T): Basket[T]; 
function f3 <T extends keyof Basket>(t: string): Basket[keyof Basket] {
    if (t == 'Fruit') {
        return  'banana'
    } else {
        return  'tomato'
    }
}

const complies2 = f3('Fruit'); // complies2 is "banana"

注意:箭头函数不适用于函数重载。