空映射和数组的 typescript 类型

标签 typescript

在 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 saying foo: {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/

相关文章:

对象属性路径的 TypeScript 类型定义

Angular 2获取div的宽度

javascript - Angular :输入时模糊输入

html - 如何使用 `<a>` 链接标记以 Angular 4 提交表单

typescript - 使用不同类型的属性扩展 `Record<string, string[]>`

module - 导入位于低于当前路径的路径中的 TypeScript 模块会引发范围错误

c# - 两种类型的变量

angularjs - angular2 http 类型错误

javascript - 为什么 Date.now() | 0 与 Date.now() 不同

node.js - 找不到命名空间 'NodeJS' 也有类型 Node