首页 > 解决方案 > 通过字段推断文字对象联合的类型

问题描述

我在界面中有一些单独的属性。将这些属性划分为两个接口,然后声明两者的联合类型似乎是可行的方法。

请看下面的简化情况,其中函数需要百分比或固定值。向每个接口添加一个道具,说明其是否为一种类型(isPercent)并将类型限制为特定值,允许函数的逻辑检测传递的参数的类型,并且打字稿 - 令人惊讶地 - 似乎也可以推断类型但仅.

很难描述它,但我希望代码能给你这个想法:

interface IPcentFee { isPercent: true, percentFee: number }
interface IFixedFee { isPercent: false, fixedFee: number }

let parm = { isPercent: true, percentFee: 0.15 }

function calculate(parm:IPcentFee | IFixedFee){
    let value = 100, discount
    if (parm.isPercent) 
        discount = value * parm.percentFee  // Here ts infers type of parm being IPecentFee
    else 
        discount = parm.fixedFee    // ts error: Property 'fixedFee' does not exist on type 'IPcentFee | IFixedFee'
    ....
}

TS 似乎从条件推断类型 IPcentFeeif (parm.isPercent)但为什么 else 子句不推断替代类型?

样本通过 ts 2.9.1 版本进行分析

标签: typescripttype-inference

解决方案


这确实很有趣。

看这个:

interface IPcentFee { isPercent: true, percentFee: number }
interface IFixedFee { isPercent: false, fixedFee: number }

let parm = { isPercent: true, percentFee: 0.15 }

function calculate(parm:IPcentFee | IFixedFee){
    let value = 100, discount
    if (parm.isPercent === true) // Comparing to literal `true`
        discount = value * parm.percentFee
    else 
        discount = parm.fixedFee // it works!
}

操场

只需更改if (parm.isPercent)to 即可if (parm.isPercent === true)完成工作,并且每个分支中的类型都按预期缩小。我不得不承认我不完全确定为什么另一种方式不起作用。我想这是由于truthy/true差异造成的......但是,如图所示,您可以与文字值进行比较,因此您无需手动断言。

更新:

事实上,它看起来是由于差异,但不是truthy/true而是falsy/ false。如果您启用该strictNullChecks标志,您的代码就可以正常工作。

如果strictNullChecks未启用,默认情况下每种类型都可以为空,因此您仍然需要isPercent检查null/ undefined。启用该标志使每个类型默认情况下都不可为空,因此实际上只有两种可能性(至于类型检查)是trueor false


推荐阅读