【发布时间】:2020-12-28 15:44:14
【问题描述】:
设置:给定一些打字稿代码,例如:
type ObjectList = {
[index: string]: string;
};
function makeList(input: ObjectList | string | number): string[] {
if (typeof input === "string" || typeof input === "number") {
return [String(input)];
}
const arr = [];
for (const x in input) {
arr.push(String(input[x]));
}
return arr;
}
// Turns a number into a string array
console.log(makeList(123));
// Turns a string into an array
console.log(makeList("hello"));
// Turns an object dictionary into an array
console.log(makeList({ a: "A", b: "B" }));
好的,很简单,而且效果很好。对类型安全至关重要的是这一行:
if (typeof input === "string" || typeof input === "number") {
它确保for in 将只在ObjectList 上运行,TypeScript 编译器很好地为我们嗅出它!这里的缺点是那行代码非常冗长,尤其是如果您要添加更多类型,或者我们应该能够做到这一点:
if (['string', 'number'].includes(typeof input)) {
但是,这将导致 TypeScript 编译器错误,基本上表明 for loop 不确定 string 和 number 类型无法访问它。
'for...in' 语句的右侧必须是 'any' 类型、对象类型或类型参数,但这里有类型 'string |号码 |对象列表
这是一个运行示例:
https://codesandbox.io/s/typescript-arrayincludestypeof-var-dblkn?file=/src/index.ts
问题:为了更好地理解编译器——我对编译器为何表现出这种行为感兴趣。 [].includes() 与编译器不兼容怎么办?静态分析是不是太深了?有没有我没有想到的运行时注意事项?在比较中使用时,TS 中的 typeof 运算符是否绑定了一些额外的“魔法”?
【问题讨论】:
-
"是不是静态分析太深了?"是的。如果打字稿必须检查每个数组的值并记住对这些数组进行操作的每个函数的逻辑,那会慢很多。
-
我很好奇 - 添加
any类型转换能解决问题吗?就像,这行得通吗?if (['string', 'number'].includes(typeof (input as any))) { -
当你有一个 if 语句来缩小类型时,Typescript 会进行分析,但它只在非常基本的级别上执行此操作。如果您需要更复杂的东西,您可以定义自己的函数来缩小类型 - 此功能称为类型保护,请参阅:typescriptlang.org/docs/handbook/…
-
如果你想为你的代码保证类型安全,不要改变你的数组。 TS不喜欢
标签: typescript