Typkontroll mellan klass och objektsliteral i TypeScript


I TypeScript kan ett objektliteral tilldelas en variabel typad som en klass om objektet tillhandahåller alla egenskaper och metoder som klassen behöver.

class MyClass {
  a: number;
  b: string;
}

// Compiler won't complain
const instance: MyClass = { a: 1, b: '' };

// Compiler won't complain if I assign an object with more properties
const literal = { a: 1, b: '', c: false };
const instance2: MyClass = literal;

Det jag vill göra här är att förhindra denna typ av uppdrag baserat på två skäl:

  1. instance instanceof MyClass borde vara sant;
  2. Jag kan tilldela ett objekt med fler egenskaper (se ovan).

På detta sätt fungerar TypeScript-klass mer som ett gränssnitt. Finns det ett sätt jag kan förhindra detta?

Svar #1

Från TypeScript-dokumentationen verkar det du observerar vara det förväntade beteendet:

Typkompatibilitet i TypeScript baseras på strukturell subtypning. Strukturell typning är ett sätt att relatera typer endast baserat på deras medlemmar.

Så om två typer har samma struktur är det avsett att objekt av dessa typer kan tilldelas varandra.

Det finns en öppen funktionsförfrågan på microsoft/TypeScript#29063 som ber om ett sätt att skilja klasser instanstyper från strukturellt identiska objekttyper, men för närvarande är det inte en del av språket.

Tillfällig lösning: privata medlemmar

När du börjar lägga till privata medlemmar till en klass (vilket du nästan alltid gör i praktiken), fungerar typkontrollen mycket närmare hur du vill.

class MyClass {
  a: number;
  b: string;
  private c: number;
}

// "Property 'c' is missing in type '{ a: number; b: string; }' but required in type 'MyClass'."
const instance: MyClass = { a: 1, b: '' };

// "Property 'c' is private in type 'MyClass' but not in type '{ a: number; b: string; c: number; }'"
const literal: MyClass = { a: 1, b: '', c: 3 };

class OtherClass {
  a: number;
  b: string;
  private c: number;
}

// "Types have separate declarations of a private property 'c'"
const otherClass: MyClass = new OtherClass();

Svar #2

Jag vet inte om jag förstod din fråga korrekt, men det jag drar från din kod är att.

I din andra uppgift är variabeln literal inte definierad som typen MyClass

const literal = { a: 1, b: '', c: false };

Så, du försöker bara skapa en konstant variabel med några värden.

Relaterade artiklar