我们有以下代码段:
interface A {
isEmpty(x: any[] | string | object): boolean;
isEmptyObject(x: object): boolean;
}
const a: A = <A>{};
a.isEmptyObject({});
a.isEmptyObject({a: 1});
a.isEmpty([]);
a.isEmpty('');
a.isEmpty({});
a.isEmpty({a: 1});
当我尝试编译它时,它会崩溃:
a.ts(14,12): error TS2345: Argument of type '{ a: number; }' is not assignable to parameter of type 'string | object | any[]'.
Object literal may only specify known properties, and 'a' does not exist in type 'string | object | any[]'.
如果联合类型( string | object | any[]
)包含它可以工作的类型 object
(使用 {a: 1}
的 isEmptyObject
调用正常),这怎么可能?
主要问题:这是一个TypeScript错误,或者应该如何编写输入可能是任何值或字符串或对象的数组(但不是任何原语,我不想 any
或 Object
)?
使用TypeScript 2.3.4进行测试 .
3 回答
这不是一个错误,而是一个支持使用参数对象的API的功能 . 以jQuery-s ajax函数为例 . 它将一个对象作为参数 .
You do want a compilation error in this case ,即使
{url:"",datta:""}
实现了param接口 . 为了解决这个问题,他们添加了excess property checks for object literals as direct parameters . This is a good thing ,在类型检查器中提供更多信心,并且只有在人们尝试像您一样进行快速测试时才会导致错误 . 您必须牢记这一规则,这是额外安全的成本 .UPDATE: TypeScript 2.4另外介绍Weak types
那么有这个签名的函数:
在这里,意图很明确,这个功能旨在接受任何键的任何对象 . 仅接受空对象的函数几乎没有用处 . 所以他们添加了一个例外:当参数的类型为
object
时,则省略前一个检查 .那么该怎么办?没有 . 在实际使用中,你的功能会很好地检测 . 你可以尝试一下:
UPDATE
您的示例是一个实际的用例,您希望它甚至可以使用文字 . 在Nitzan之后,我也建议使用函数重载 .
您可以通过添加其他签名轻松解决此问题:
(code in playground)
编辑
我不认为这是一个错误,如果有任何错误,这是错误消息,这是不是很有帮助 .
我认为发生的事情是你可以在任何原始类型的联合中使用
object
而没有问题(在你的情况下),但是一旦你引入了非原始类型,那么你将得到错误,例如:会导致同样的错误 .
object
(这是非原始的)和另一个非原始类型的并集可能导致一种无法匹配的类型,并且编译器会混淆 .欢迎您在此案例中打开一个新问题,如果您这样做,请在此处分享链接,我想看看他们说了什么 .
Typescript在以下条件下编译失败:
Object literal may only specify known properties, and 'a' does not exist in type 'string | object | any[]'.
基本上
{ a: 1 }
不能转换为object
类型 .你可以这样做:
编辑:接下来看看docs它可能解释为: