第 27 期 - Object Property Order's Impact on TypeScript Type Inference
摘要
阐述了 TypeScript 中对象属性顺序对类型推断有影响,以一个函数为例展示正常与异常情况,提到 TypeScript 4.7 版本对此的改进,还探讨了 NoInfer 无法解决相关问题。
一、函数示例中的正常类型推断
在示例中创建了一个函数process
,它接受一个对象作为参数,对象包含produce
和consume
两个属性。
const process = <T>(obj: {
produce: (input: string) => T;
consume: (t: T) => void;
}) => {
const value = obj.produce("abc");
obj.consume(value);
};
当按照正常顺序定义produce
和consume
属性时,如:
process({
produce: (input) => Number(input),
consume: (output) => console.log(output), (parameter) output: number
});
TypeScript 能够正确推断produce
返回值的类型并传递给consume
。并且可以适用于不同类型的值,例如:
process({
produce: (input) => input + "hello",
consume: (output) => console.log(output), (parameter) output: string
});
process({
produce: (input) => ({ value: input }),
consume: (output) => console.log(output), (parameter) output: {
value: string;
}
});
二、属性顺序改变后的类型推断问题
当用户将consume
放在produce
之前时,就会出现问题:
process({
consume: (output) => console.log(output), (parameter) output: unknown
produce: (input) => Number(input),
});
此时TypeScript
将output
视为unknown
,尽管produce
函数明显返回一个数字。这是因为自TypeScript 4.7
版本起,会根据属性顺序进行类型推断,这一改变是为了解决一些长期存在的与上下文敏感函数相关的漏洞。
三、NoInfer 无法解决该问题
有人可能会想是否可以使用NoInfer
来解决这个问题,毕竟NoInfer
用于强制TypeScript
避免对某些目标进行推断。但是:
const process = <T>(obj: {
produce: (input: string) => T;
consume: NoInfer<(t: T) => void>;
}) => {
const value = obj.produce("abc");
obj.consume(value);
};
process({
consume: (output) => console.log(output), (parameter) output: unknown
produce: (input) => Number(input),
});
结果仍然是unknown
,令人沮丧。
扩展阅读
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有