通过字段推断文字对象的类型

时间:2018-06-14 22:14:44

标签: typescript type-inference

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

请查看以下简化情况,其中函数需要百分比或固定值。向每个接口添加一个prop,表明它的一个类型(isPercent)并将类型约束为特定值,允许函数的逻辑检测传递的参数类型和typescript -amazingly-似乎也推断类型但仅。

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

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似乎从条件if (parm.isPercent)推断类型IPcentFee,但为什么else子句不推断替代类型?

通过ts 版本2.9.1

分析样品

2 个答案:

答案 0 :(得分:3)

确实非常有趣。

看看这个:

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!
}

Playground

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

<强>更新

事实上,它看起来是一个差异,但不是truthy / true而是falsy / false。如果您启用了strictNullChecks标记,那么您的代码就可以正常运行。

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

答案 1 :(得分:0)

带有接口的联合类型在Typescript中很有趣,通常需要具有公共属性才能直接引用它们。所以你的界面可能是:

interface IPcentFee { isPercent: true, fee: number }
interface IFixedFee { isPercent: false, fee: number }

并访问:

discount = value * parm.fee

fee可能很常见,因为您正在检查公共财产isPercent

或者,您可以在else子句中强制转换为以下内容,这不会引发任何错误。

discount = (<IFixedFee>parm).fixedFee 

Playground