X. Liu
X. Liu

Reputation: 33

Type check between class and object literal in TypeScript

in TypeScript, an object literal can be assigned to a class typed variable if that object provides all properties and methods that the class needs.

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;

What I want to do here is to prevent this kind of assignment based on two reasons:

  1. instance instanceof MyClass should be true;
  2. I can assign an object with more properties (see above).

In this way, TypeScript class works more like an interface. Is there a way I can prevent this?

Upvotes: 3

Views: 926

Answers (2)

ecraig12345
ecraig12345

Reputation: 2437

From the TypeScript docs, what you're observing seems to be the expected behavior:

Type compatibility in TypeScript is based on structural subtyping. Structural typing is a way of relating types based solely on their members.

So if two types have the same structure, it's intended that objects of those types can be assigned to each other.

There is an open feature request at microsoft/TypeScript#29063 asking for some way to distinguish class instance types from structurally identical object types, but for now it's not part of the language.

Workaround: private members

Once you start adding private members to a class (which you'd almost always do in practice), the type checking works much closer to how you want.

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();

Upvotes: 4

dileepkumar jami
dileepkumar jami

Reputation: 2265

I don't know if I understood your question correctly but what I infer from your code is that.

In your second assignment, the variable literal is not defined as the type MyClass

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

So, you are just trying to create a const variable with some values.

Upvotes: 0

Related Questions