typescript - 为什么使用条件运算符会导致交集类型?
问题描述
我正在尝试创建一个通用函数,该函数根据其参数的类型有条件地返回值,但我一直在尝试实现返回类型。
假设有一个类型Basket
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.
但是,如果我不使用泛型,我会得到一个 sum 类型
//This compiles
const f2 = <T extends keyof Basket>(t: string): Basket[keyof Basket] => { //return type is 'banana' | 'tomato'
if (t == 'yellow') {
return 'banana'
} else {
return 'tomato'
}
}
const complies: 'banana' | 'tomato' = f2<'Fruit'>('') //type: 'banana' | 'tomato', but I want the type here to be 'banana'
现在它编译得很好,但我失去了类型安全的好处。
在保留泛型的同时如何让这个示例工作?任何帮助都深表感谢。
解决方案
关于您的问题,它来自延迟的条件类型。查看打字稿文档: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"
注意:箭头函数不适用于函数重载。
推荐阅读
- android - android - 调用系统属性 fin AndroidStudio rom R 版本
- api - Laravel:Billbee Api - Guzzle 错误 - 魔术请求方法需要 URI 和可选选项数组
- pycharm - 如何同步运行 PyCharm 文件观察器?
- node.js - 文件未显示在 IPFS 上的 NFT 存储中
- flutter - 如何在 Flutter 中更改 AppBar() 的宽度?
- macos - 为什么会出现此错误“配置:错误:检查配置。”?
- r - ggalluvial:增加每个类别之间的空间?
- c++ - 错误:重载函数的调用不明确
- javascript - 使用 jQuery 发布 JSON 后,将字符串转换回 JSON
- c - 为什么预处理器禁止宏粘贴奇怪的标记