gpt4 book ai didi

Typescript - 如何在 switch 语句中缩小泛型类型的类型可能性?

转载 作者:行者123 更新时间:2023-12-04 12:17:04 25 4
gpt4 key购买 nike

我正在尝试编写一个函数,该函数将根据传递的键和参数执行特定计算。我还想强制传递的键和参数之间存在关系,所以我使用了一个带有约束的泛型函数:

interface ProductMap {
one: {
basePrice: number;
discount: number;
},
two: {
basePrice: number;
addOnPrice: number;
}
}

function getPrice<K extends keyof ProductMap>(key: K, params: ProductMap[K]) {
switch (key) {
case 'one': {
return params.basePrice - params.discount; // Property 'discount' does not exist on type 'ProductMap[K]'.
}
case 'two': {
return params.basePrice + params.addOnPrice;
}
}
}


也许我以错误的方式思考这个问题,但似乎 typescript 应该能够缩小 switch 语句中的泛型类型。我可以让它工作的唯一方法就是这种尴尬:
function getPrice<K extends keyof ProductMap>(key: K, params: ProductMap[K]) {
switch (key) {
case 'one': {
const p = params as ProductMap['one'];
return p.basePrice - p.discount;
}
case 'two': {
const p = params as ProductMap['two'];
return p.basePrice + p.addOnPrice;
}
}
}

谁能解释为什么#1 不起作用或提供替代解决方案?

最佳答案

“谁能解释为什么#1 不起作用或提供替代解决方案?”

这就是 #1 不起作用的原因:Typescript 有 control-flow type narrowing对于像 key 这样的变量,但不适用于像 K 这样的类型参数.
case 'one': check 缩小了变量的类型 key: Kkey: 'one' .

但它并没有从 K extends 'one' | 'two' 缩小至 K extends 'one' ,因为没有对实际的类型变量K做过测试,也不能做任何测试来缩小它。所以params: ProductMap[K]还在params: ProductMap[K] , 和 K仍然是相同的类型,所以 params 的类型没有缩小。

这是一个替代解决方案:使用可区分的联合,并打开可区分的(即下面代码中的 __tag 属性)。

type ProductMap =
{
__tag: 'one';
basePrice: number;
discount: number;
} | {
__tag: 'two';
basePrice: number;
addOnPrice: number;
}

function getPrice(params: ProductMap): number {
switch (params.__tag) {
case 'one': {
return params.basePrice - params.discount;
}
case 'two': {
return params.basePrice + params.addOnPrice;
}
}
}

Playground Link

关于Typescript - 如何在 switch 语句中缩小泛型类型的类型可能性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075083/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com