8.1 Class Declarations

A class declaration declares a class type and a constructor function.

  ClassDeclaration: ( Modified )   classBindingIdentifieroptTypeParametersoptClassHeritage{ClassBody}

A ClassDeclaration introduces a named type (the class type) and a named value (the constructor function) in the containing declaration space. The class type is formed from the instance members declared in the class body and the instance members inherited from the base class. The constructor function is given an anonymous type formed from the constructor declaration, the static member declarations in the class body, and the static members inherited from the base class. The constructor function initializes and returns an instance of the class type.

The BindingIdentifier of a class declaration may not be one of the predefined type names (section 3.8.1). The BindingIdentifier is optional only when the class declaration occurs in an export default declaration (section 11.3.4.2).

A class may optionally have type parameters (section 3.6.1) that serve as placeholders for actual types to be provided when the class is referenced in type references. A class with type parameters is called a generic class. The type parameters of a generic class declaration are in scope in the entire declaration and may be referenced in the ClassHeritage and ClassBody.

The following example introduces both a named type called ‘Point’ (the class type) and a named value called ‘Point’ (the constructor function) in the containing declaration space.

  1. class Point {
  2. constructor(public x: number, public y: number) { }
  3. public length() { return Math.sqrt(this.x * this.x + this.y * this.y); }
  4. static origin = new Point(0, 0);
  5. }

The named type ‘Point’ is exactly equivalent to

  1. interface Point {
  2. x: number;
  3. y: number;
  4. length(): number;
  5. }

The named value ‘Point’ is a constructor function whose type corresponds to the declaration

  1. var Point: {
  2. new(x: number, y: number): Point;
  3. origin: Point;
  4. };

The context in which a class is referenced distinguishes between the class type and the constructor function. For example, in the assignment statement

  1. var p: Point = new Point(10, 20);

the identifier ‘Point’ in the type annotation refers to the class type, whereas the identifier ‘Point’ in the new expression refers to the constructor function object.

8.1.1 Class Heritage Specification

TODO: Update this section to reflect expressions in class extends clauses.

The heritage specification of a class consists of optional extends and implements clauses. The extends clause specifies the base class of the class and the implements clause specifies a set of interfaces for which to validate the class provides an implementation.

  ClassHeritage: ( Modified )   ClassExtendsClauseoptImplementsClauseopt

  ClassExtendsClause:   extendsClassType

  ClassType:   TypeReference

  ImplementsClause:   implementsClassOrInterfaceTypeList

A class that includes an extends clause is called a derived class, and the class specified in the extends clause is called the base class of the derived class. When a class heritage specification omits the extends clause, the class does not have a base class. However, as is the case with every object type, type references (section 3.3.1) to the class will appear to have the members of the global interface type named ‘Object’ unless those members are hidden by members with the same name in the class.

The following constraints must be satisfied by the class heritage specification or otherwise a compile-time error occurs:

  • If present, the type reference specified in the extends clause must denote a class type. Furthermore, the TypeName part of the type reference is required to be a reference to the class constructor function when evaluated as an expression.
  • A class declaration may not, directly or indirectly, specify a base class that originates in the same declaration. In other words a class cannot, directly or indirectly, be a base class of itself, regardless of type arguments.
  • The this-type (section 3.6.3) of the declared class must be assignable (section 3.11.4) to the base type reference and each of the type references listed in the implements clause.
  • The constructor function type created by the class declaration must be assignable to the base class constructor function type, ignoring construct signatures.

The following example illustrates a situation in which the first rule above would be violated:

  1. class A { a: number; }
  2. namespace Foo {
  3. var A = 1;
  4. class B extends A { b: string; }
  5. }

When evaluated as an expression, the type reference ‘A’ in the extends clause doesn’t reference the class constructor function of ‘A’ (instead it references the local variable ‘A’).

The only situation in which the last two constraints above are violated is when a class overrides one or more base class members with incompatible new members.

Note that because TypeScript has a structural type system, a class doesn’t need to explicitly state that it implements an interface—it suffices for the class to simply contain the appropriate set of instance members. The implements clause of a class provides a mechanism to assert and validate that the class contains the appropriate sets of instance members, but otherwise it has no effect on the class type.

8.1.2 Class Body

The class body consists of zero or more constructor or member declarations. Statements are not allowed in the body of a class—they must be placed in the constructor or in members.

  ClassElement: ( Modified )   ConstructorDeclaration   PropertyMemberDeclaration   IndexMemberDeclaration

The body of class may optionally contain a single constructor declaration. Constructor declarations are described in section 8.3.

Member declarations are used to declare instance and static members of the class. Property member declarations are described in section 8.4 and index member declarations are described in section 8.5.