在 typescript 中,我如何表达一个函数只接受一个空映射或数组?
类似这样的东西(但它不起作用):
function foo(emptyMapOrArray: {} | []) {
//...
}
// This should error
foo(["a"])
foo({a: 1})
// This should work
foo([])
foo({})
用例是我希望能够将“原子”值分配给 JSON 文档的一部分。类似于此 paper 中使用的光标.所以一个更完整的例子是这样的:
function assign(map: {}, key: string, value: string | number | boolean | {} | []) {
map[key] = value
}
但是我意识到我可以将空映射和空数组建模为单独的操作。但我仍然认为了解 typescript 中的类型系统在这种情况下的表现力是多么有趣。
最佳答案
如 Paleo 所说,您可以使用 { [index: string]: never }
检查空对象.
但是,TypeScript 只能强制执行您放入数组中的元素的类型,它无法为您检查数组的长度,因此您的问题的第二部分对于 TypeScript 是不可能的。
This issue on GitHub对此有一些评论(强调我的):
-
Our view is that tuple is an array for which we have static knowledge of the individual types of the first N elements and for which the element type is the union of the types of those N elements. We allow more than N elements to be present (since there's really not much we can do to prohibit it), but we do require those elements to have a compatible type.
-
When realizing that there is no checking on the number of array elements the tuple feature doesn't seem as attractive as it did in my first impression.
-
Tuples are basically objects with numeric properties. So
foo: [string, string]
is like sayingfoo: {0: string, 1: string}
. -
According to the spec section 3.3.3, the type
[number, string]
is equivalent to an interface that extends Array:interface NSPair extends Array<number | string> { 0: number, 1: string }
如果你尝试像后者那样实现一个接口(interface),你会得到一个错误:
interface EmptyArray extends Array<any> { 0: never; }
const doesntWork: EmptyArray = [];
给出的错误是 TS2322: Type 'undefined[]' is not assignable to type 'EmptyArray'. Property '0' is missing in type 'undefined[]'.
如果您尝试 extends Array<never>
,错误是一样的。基本上无论您如何尝试争论定义,您都会遇到错误。
我的理解是.length
是运行时属性。 TypeScript 必须运行您的代码来检查它,这是它做不到的。
关于空映射和数组的 typescript 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43718392/