typescript - Arraydestrukturering inuti objekt


Skapa en enkel array och destrukturera den inuti ett (tomt) objekt:

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

Borde inte typkontrollen misslyckas här? bar ser inte ut som en array för mig. Editorn klagar inte alls och behandlar bar som en arraytyp även om jag enkelt kan kontrollera vid körning att det inte är det.

Redigera

Återge det enkelt i TypeScript-lekplatsen.

Svar #1

Det verkar vara ett känt problem eftersom {...foo}-destrukturering kompileras till Object.assign({}, foo), och Object.assign() deklareras som

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

så när det andra argumentet är en array, är resultatet kompatibelt med arraytypen.

Förhoppningsvis kommer det att åtgärdas när bättre typning för Object.assign implementeras:

Jag är nära att ha en PR för spridningstyper, så när de är på plats kommer Object.assign att ändras för att ha rätt typ:

assign(target: T, source: U): { ...T, ...U }

Om det implementeras korrekt bör spridningstyper inte ta hänsyn till icke-uppräkningsbara egenskaper som length, så din kod kommer då att ge samma fel som

const p: Array<number> = {};

// Type '{}' is not assignable to type 'number[]'.
// Property 'length' is missing in type '{}'.

Svar #2

Låt oss titta på den resulterande 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);

Så du skapar i princip ett objekt med samma egenskaper som den ursprungliga destrukturerade arrayen - och eftersom TypeScript är strukturellt typad kommer det att betrakta det nya objektet som kompatibelt med Array eftersom det kopierades ytligt.

Å andra sidan, om du kommer att göra:

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

Resultatet kommer att vara som förväntat en ny instans av arrayen.

Relaterade artiklar