Shapes

Underneath TypeScript is JavaScript, and underneath JavaScript is typically aJIT (Just-In-Time compiler). Given JavaScript's underlying semantics, typesare typically reasoned about by "shapes". These underlying shapes work likeTypeScript's interfaces, and are in fact how TypeScript compares custom typeslike classes and interfaces.

Consider an expansion of the previous example:

  1. interface Action {
  2. type: string;
  3. }
  4. let a: Action = {
  5. type: 'literal'
  6. }
  7. class NotAnAction {
  8. type: string;
  9. constructor() {
  10. this.type = 'Constructor function (class)';
  11. }
  12. }
  13. a = new NotAnAction(); // valid TypeScript!

Despite the fact that Action and NotAnAction have different identifiers,tsc lets us assign an instance of NotAnAction to a which has a type ofAction. This is because TypeScript only really cares that objects have thesame shape. In other words if two objects have the same attributes, with thesame typings, those two objects are considered to be of the same type.

原文: https://angular-2-training-book.rangle.io/handout/features/shapes.html