本篇是**「一起学习** TypeScript **」**系列的第6篇,接下来笔者将持续深耕,不定时更新一系列精彩纷呈的TypeScript文章,旨在解答使用TypeScript过程中的各种疑难杂症,一起探索TS的无穷魅力!
【TS系列回顾】:
TS系列(1): React中能否使子组件实现“类型安全”?
对象中定义每个属性的顺序会对类型推断有影响么?带着这个疑问,让我们先来看一个简单的例子:
一、例子
假设我们创建一个函数process,它的参数是一个对象:其中包含属性produce和属性consume
我们使用泛型,将produce属性的返回值类型作为consume属性的参数类型
const process = <T>({
produce:(input: string) => T;
consume: (t:T) => void;
}) => {
const value = obj.produce("abc")
obj.consume(value)
}
现在来使用上面的函数:
二、问题
上面👆🏻的例子看起来一切运转正常,没有任何问题。直到某天,有个同事使用了这个函数,但是它的类型推断不起作用:
output被TS推断为unknown类型!这是为什么呢?
我们可以看到produce函数已经明确地返回一个numbe类型,为何没起作用呢🤔
🔎仔细观察后,我们可以发现同事使用时,将consume定义在了produce之前。难道属性的顺序会有影响么?
在TS4.7的某次PR之后,TS使用参数对象中的属性顺序来推断类型。这是为了修复上下文相关函数中的各种已长期存在的错误(详细可见PR链接中的内容)
这意味着,在某些特定的场景中,你定义属性的顺序对TS类型推断是有影响的! 因此,如果你曾遇到过与属性排序有关的奇怪错误,这就是原因!
三、可以使用 NoInfer解决么?
有人会提出疑问,针对上述属性顺序影响了类型推断的问题,我使用NoInfer来强制TS不对某些目标进行推理,不就可以了么?
NoInfer的主要作用是在泛型编程中阻止类型推断。在TypeScript中,泛型函数能够根据传入的参数自动推断类型,但在某些情况下,这种自动推断可能不符合预期,导致不合法的函数调用被接受,而合法的调用却被拒绝。为了处理这种情况,开发者通常需要添加额外的类型参数来约束函数的行为,确保类型安全。NoInfer允许开发者明确告诉编译器哪些类型不应该被自动推断,从而增强了代码的类型安全性
实际上,使用NoInfer并不能达到想要的效果:
结果仍然是 unknown😅😅
所以,在上述场景下,还是需要注意对象中属性的定义顺序才能达到预期效果!