javascript - De ce pot atribui proprietăți necunoscute unui obiect literal în TypeScript?


  type ExpectedType = Array<{ name: number, gender?: string }>

  function go1(p: ExpectedType) {

  }  

  function f() {
    const a = [{name: 1, age: 2}]
    go1(a)                   // doesn't complain
    go1([{name: 1, age: 2}]) // complain 'Object literal may only specify known...'
    go1(['no matter'].map(n => ({name: 1, age: 2}))) // doesn't complain
  }

Codul TypeScript este ca mai sus, întrebarea mea este: ultimele trei linii nu sunt la fel? De ce prima linie trece, iar a doua linie primește o reclamație, iar a treia linie trece?

De asemenea, pe terenul de joacă TypeScript: teren de joacă

Răspuns #1

Când atribuiți variabila a parametrului funcției go1(), pare că atribuiți variabila a altei variabile para. În acest caz, deoarece tipul lui a este compatibil cu tipul variabilei parametrului. Dar dacă schimbați tipul în { name: number, gender: string }, veți avea în continuare eroare de tip.

Atunci când se atribuie un obiect literal ca parametru, nu există nicio conversie de tip în acest caz, astfel încât compilatorul poate detecta această eroare de tip.

Mai multe detalii se referă aici.

Regula de bază pentru sistemul de tipuri structurale al TypeScript este că x este compatibil cu y dacă y are cel puțin aceiași membri ca x. De exemplu:

interface Named {
    name: string;
}

let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: "Alice", location: "Seattle" };
x = y;

Pentru a verifica dacă y poate fi atribuit lui x, compilatorul verifică fiecare proprietate a lui x pentru a găsi o proprietate corespunzătoare compatibilă în y. În acest caz, y trebuie să aibă un membru numit name care să fie un șir de caractere. Are, așa că atribuirea este permisă.

Răspunsul #2

După câteva cercetări, am descoperit că răspunsul se află în documentația TypeScript.

Deci diferența dintre ultimele 3 linii este că: Parametrul din a 2-a linie este literal obiect, în timp ce ceilalți 2 nu sunt, TypeScript tratează diferit parametrii literali și parametrii non-literali:

Verificări pentru proprietăți excedentare