Spreadoperator som tar bort typdefinition i TypeScript


Jag stötte på detta märkliga fenomen i TypeScript. När jag använder spread-operatorn verkar typkontrollen förloras. Jag skulle förvänta mig att detta skulle ge ett fel:

interface Input {
  thingOne: string;
  thingTwo: number;
  thingThree: string;
  thingFour: boolean;
  thingFive: Array<number>
}

interface Output {
  thingThree: string;
  thingFour: boolean;
  thingFive: Array<number>
}

const transformFunction = (input: Input): Output => {
  const result: Output = {
    ...input,
    thingFour: !input.thingFour
  }
  return result
}

Typescript-lekplats exempel

Jag skriver result som Output, men att sprida ett objekt av typen Input i det skulle tydligt producera ett resultat som inte är av typen Output. Varför fångar inte TypeScript detta?

Svar #1

Det vi förväntar oss här är att trigga funktionen Excess Property Check i TypeScript. Denna funktion talar om för oss att TypeScript skulle varna oss om det finns extra egenskaper i objektet om vi uttryckligen anger objekttypen. Tyvärr fungerar det endast för objektliteraler.

Till exempel detta:

const transformFunction = (input: Input): Output => {
  return {
    thingOne: "string;",
    thingTwo: 123,
    thingThree: "string;",
    thingFour: !input.thingFour,
    thingFive: [1, 23],
  };
};

Varnar :

Type '{ thingOne: string; thingTwo: number; thingThree: string; thingFour: boolean; thingFive: number[]; }' is not assignable to type 'Output'.
  Object literal may only specify known properties, and 'thingOne' does not exist in type 'Output'.

Det verkar som att spread-operatörsfall inte täcks under kontroll av exces-egenskap. Se här: https://github.com/microsoft/TypeScript/issues/41237

Detta är kontrollen av överskottsattribut. Enligt @RyanCavanaugh är det mer av en linter, inte riktigt en del av typesystemet. Men inte varje fall täcks av denna kontroll, som du märkte.

De nämnde också att de ska titta på pågående konvertering av exakta typer här: https://github.com/microsoft/TypeScript/issues/12936

Svar #2

Funktionen är typkorrrekt eftersom typ Input kan tilldelas typ Output utan problem, även om den har extra egenskaper. Endast för bokstavliga objekt finns en kontroll av överflödiga egenskaper, eftersom överflödiga egenskaper i ett objektliteral sannolikt är misstag. Betrakta denna konstant som exempel.

const o: {a: number} = {a: 1, b: 2}

Eftersom o nu har typen {a: number}, finns det inget typat sätt att komma åt egenskapen b, så TypeScript betraktar det som ett fel.

Relaterade artiklar