带有索引签名的 keyof 类型运算符
keyof type operator with indexed signature
我正在阅读打字稿 docs 并阅读了这段代码摘录:
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
他们给出了如下解释:
Note that in this example, M is string | number — this is because JavaScript object keys are always coerced to a string, so obj[0] is always the same as obj["0"].
所以我的问题是为什么只 number
?为什么不 boolean
或 object
?
TypeScript 支持 string
和 number
index signatures, and (starting with TypeScript 4.4) symbol
and pattern template literal index signatures。 JavaScript 中的对象只有 string
和 symbol
键,所以 string
、symbol
和模式模板文字(它们是 [=12 的子类型) =]) TypeScript 中的索引签名应该很有意义。但是 number
是怎么回事?
数字索引签名专门用于支持 arrays 和其他类似数组的对象。如果使用数字索引索引数组会产生 TypeScript 错误:
const arr = ["a", "b", "c"];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i].toUpperCase());
// -----------> ~ <-- error, you can't index with a number?
}
要求 non-idiomatic JavaScript 如 arr[String(i)]
会很不方便。它甚至无济于事;编译器无法真正区分 String(1)
和任何其他字符串之间的区别,因此它不会理解 arr[String(1)]
应该是数组的元素,而不是像 [=24= 这样的方法].
因此,即使对象实际上并没有 number
值键,TypeScript 假装 它们这样做是为了更自然地支持数组,因为数组非常通常与惯用 JavaScript 代码中的数字索引一起使用。
另一方面,没有人使用其他对象或 boolean
键索引到 JavaScript 个对象:
// nobody does this
const foo = { true: 1, false: 0, "[object Object]": 2 };
console.log(foo[Math.random() < 0.5]) // what
console.log(foo[{ a: 123 }]); // what are you doing
嗯,也许不是 nobody,但是像 foo[false]
或 foo[{}]
这样的代码更可能是编程错误的情况非常罕见预期的代码。所以 TypeScript 没有理由允许 boolean
或 object
索引签名。
我正在阅读打字稿 docs 并阅读了这段代码摘录:
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
他们给出了如下解释:
Note that in this example, M is string | number — this is because JavaScript object keys are always coerced to a string, so obj[0] is always the same as obj["0"].
所以我的问题是为什么只 number
?为什么不 boolean
或 object
?
TypeScript 支持 string
和 number
index signatures, and (starting with TypeScript 4.4) symbol
and pattern template literal index signatures。 JavaScript 中的对象只有 string
和 symbol
键,所以 string
、symbol
和模式模板文字(它们是 [=12 的子类型) =]) TypeScript 中的索引签名应该很有意义。但是 number
是怎么回事?
数字索引签名专门用于支持 arrays 和其他类似数组的对象。如果使用数字索引索引数组会产生 TypeScript 错误:
const arr = ["a", "b", "c"];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i].toUpperCase());
// -----------> ~ <-- error, you can't index with a number?
}
要求 non-idiomatic JavaScript 如 arr[String(i)]
会很不方便。它甚至无济于事;编译器无法真正区分 String(1)
和任何其他字符串之间的区别,因此它不会理解 arr[String(1)]
应该是数组的元素,而不是像 [=24= 这样的方法].
因此,即使对象实际上并没有 number
值键,TypeScript 假装 它们这样做是为了更自然地支持数组,因为数组非常通常与惯用 JavaScript 代码中的数字索引一起使用。
另一方面,没有人使用其他对象或 boolean
键索引到 JavaScript 个对象:
// nobody does this
const foo = { true: 1, false: 0, "[object Object]": 2 };
console.log(foo[Math.random() < 0.5]) // what
console.log(foo[{ a: 123 }]); // what are you doing
嗯,也许不是 nobody,但是像 foo[false]
或 foo[{}]
这样的代码更可能是编程错误的情况非常罕见预期的代码。所以 TypeScript 没有理由允许 boolean
或 object
索引签名。