创建一个简单的数组并在(空)对象中对其进行解构:
const foo: Array<number> = [1, 2, 3, 4];
const bar: Array<number> = {...foo};
这种类型检查不应该失败吗? bar
对我来说看起来不像是一个数组。
编辑器根本没有抱怨并将bar
视为数组类型,即使我可以在运行时轻松检查它不是。
修改
答案 0 :(得分:3)
让我们看看结果javascript:
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var foo = [1, 2, 3, 4];
var bar = __assign({}, foo);
因此,您基本上创建了一个与原始析构数组具有相同属性的对象 - 并且作为typescript是structural typed,它会认为新对象与Array兼容,因为它是浅层复制的。
另一方面,如果你这样做:
const foo1: Array<number> = [1, 2, 3, 4];
const bar1: Array<number> = [...foo1];
结果将是预期的数组新实例。
答案 1 :(得分:2)
它看起来像一个已知问题,因为{...foo}
解构被编译为Object.assign({}, foo)
,而Object.assign()
被声明为
assign<T, U>(target: T, source: U): T & U;
所以当第二个参数是一个数组时,结果与数组类型兼容。
希望在better typing for Object.assign is implemented:
时修复我接近有传播类型的公关,所以当它们在, Object.assign将更改为具有正确的类型:
assign(target:T,source:U):{... T,... U}
如果正确实施,点差类型不应考虑不可枚举的属性,例如length
,那么您的代码将提供与
const p: Array<number> = {};
// Type '{}' is not assignable to type 'number[]'.
// Property 'length' is missing in type '{}'.