对象内部的数组解构

Array destructuring inside object

创建一个简单的数组并在一个(空)对象中解构它:

const foo: Array<number> = [1, 2, 3, 4];
const bar: Array<number> = {...foo};

这里的类型检查不应该失败吗? bar 在我看来不像是数组。 编辑器根本没有抱怨并将 bar 视为数组类型,即使我可以在运行时轻松检查它不是。

编辑

Reproducing it easily in the TypeScript playground.

让我们看看结果 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);

因此,您基本上创建了一个与原始解构数组具有相同属性的对象 - 由于打字稿是 structural typed 它会考虑与数组兼容的新对象,因为它是浅复制的。

另一方面,如果您愿意:

const foo1: Array<number> = [1, 2, 3, 4];
const bar1: Array<number> = [...foo1];

结果将是数组的新实例。

它看起来像是一个已知问题,因为 {...foo} 解构被编译成 Object.assign({}, foo),并且 Object.assign() 被声明为

assign<T, U>(target: T, source: U): T & U;

所以当第二个参数是数组时,结果与数组类型兼容。

希望在better typing for Object.assign is implemented:

时修复

I am close to having a PR for spread types, so when those are in, Object.assign will change to have the correct type:

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 '{}'.