在打字稿中,如何表达函数只接受空映射或数组?
像这样的东西(但它不起作用):
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
}
但是我意识到我可以将空映射和空数组建模为单独的操作。但我仍然认为知道打字稿中的类型系统在这种情况下的表现力是多么有趣。
答案 0 :(得分:3)
就像Paleo所说,你可以用{ [index: string]: never }
检查空对象。
但是,TypeScript只能强制放入数组中的元素类型,它无法为您检查数组的长度,因此使用TypeScript无法解决问题的第二部分。
This issue on GitHub对此有一些评论(强调我的):
我们的观点是元组是一个数组,我们对前N个元素的各个类型有静态知识,元素类型是这些N个元素类型的并集。我们允许存在超过N个元素(因为我们无法做很多事情来禁止它),但我们确实要求这些元素具有兼容类型。
当意识到没有检查数组元素的数量时,元组特征似乎没有我在第一次印象中那么有吸引力。
元组基本上是具有数字属性的对象。所以
foo: [string, string]
就像在说foo: {0: string, 1: string}
。
根据规范第3.3.3节,类型
[number, string]
等同于扩展Array的接口:interface NSPair extends Array<number | string> { 0: number, 1: string }
如果您尝试实现类似后者的界面,则会收到错误:
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必须运行你的代码来检查它,它不能这样做。
答案 1 :(得分:1)
checkGuess()
我建议:
--strictNullChecks
注意:此代码需要编译器选项function foo(emptyMapOrArray: { [index: string]: never } | never[]) {
//...
}
。否则,语句strictNullChecks
不会编译。
foo([])
如果没有编译器选项--strictNullChecks
,您可能更喜欢:
strictNullChecks
但它并不完美:
function foo(emptyMapOrArray: { [index: string]: never } | undefined[]) {
//...
}