8.2 Members

The members of a class consist of the members introduced through member declarations in the class body and the members inherited from the base class.

8.2.1 Instance and Static Members

Members are either instance members or static members.

Instance members are members of the class type (section 8.2.4) and its associated this-type. Within constructors, instance member functions, and instance member accessors, the type of this is the this-type (section 3.6.3) of the class.

Static members are declared using the static modifier and are members of the constructor function type (section 8.2.5). Within static member functions and static member accessors, the type of this is the constructor function type.

Class type parameters cannot be referenced in static member declarations.

8.2.2 Accessibility

Property members have either public, private, or protected accessibility. The default is public accessibility, but property member declarations may include a public, private, or protected modifier to explicitly specify the desired accessibility.

Public property members can be accessed everywhere without restrictions.

Private property members can be accessed only within their declaring class. Specifically, a private member M declared in a class C can be accessed only within the class body of C.

Protected property members can be accessed only within their declaring class and classes derived from their declaring class, and a protected instance property member must be accessed through an instance of the enclosing class or a subclass thereof. Specifically, a protected member M declared in a class C can be accessed only within the class body of C or the class body of a class derived from C. Furthermore, when a protected instance member M is accessed in a property access E.M within the body of a class D, the type of E is required to be D or a type that directly or indirectly has D as a base type, regardless of type arguments.

Private and protected accessibility is enforced only at compile-time and serves as no more than an indication of intent. Since JavaScript provides no mechanism to create private and protected properties on an object, it is not possible to enforce the private and protected modifiers in dynamic code at run-time. For example, private and protected accessibility can be defeated by changing an object’s static type to Any and accessing the member dynamically.

The following example demonstrates private and protected accessibility:

  1. class A {
  2. private x: number;
  3. protected y: number;
  4. static f(a: A, b: B) {
  5. a.x = 1; // Ok
  6. b.x = 1; // Ok
  7. a.y = 1; // Ok
  8. b.y = 1; // Ok
  9. }
  10. }
  11. class B extends A {
  12. static f(a: A, b: B) {
  13. a.x = 1; // Error, x only accessible within A
  14. b.x = 1; // Error, x only accessible within A
  15. a.y = 1; // Error, y must be accessed through instance of B
  16. b.y = 1; // Ok
  17. }
  18. }

In class ‘A’, the accesses to ‘x’ are permitted because ‘x’ is declared in ‘A’, and the accesses to ‘y’ are permitted because both take place through an instance of ‘A’ or a type derived from ‘A’. In class ‘B’, access to ‘x’ is not permitted, and the first access to ‘y’ is an error because it takes place through an instance of ‘A’, which is not derived from the enclosing class ‘B’.

8.2.3 Inheritance and Overriding

A derived class inherits all members from its base class it doesn’t override. Inheritance means that a derived class implicitly contains all non-overridden members of the base class. Only public and protected property members can be overridden.

A property member in a derived class is said to override a property member in a base class when the derived class property member has the same name and kind (instance or static) as the base class property member. The type of an overriding property member must be assignable (section 3.11.4) to the type of the overridden property member, or otherwise a compile-time error occurs.

Base class instance member functions can be overridden by derived class instance member functions, but not by other kinds of members.

Base class instance member variables and accessors can be overridden by derived class instance member variables and accessors, but not by other kinds of members.

Base class static property members can be overridden by derived class static property members of any kind as long as the types are compatible, as described above.

An index member in a derived class is said to override an index member in a base class when the derived class index member is of the same index kind (string or numeric) as the base class index member. The type of an overriding index member must be assignable (section 3.11.4) to the type of the overridden index member, or otherwise a compile-time error occurs.

8.2.4 Class Types

A class declaration declares a new named type (section 3.7) called a class type. Within the constructor and instance member functions of a class, the type of this is the this-type (section 3.6.3) of that class type. The class type has the following members:

  • A property for each instance member variable declaration in the class body.
  • A property of a function type for each instance member function declaration in the class body.
  • A property for each uniquely named instance member accessor declaration in the class body.
  • A property for each constructor parameter declared with a public, private, or protected modifier.
  • An index signature for each instance index member declaration in the class body.
  • All base class instance property or index members that are not overridden in the class.

All instance property members (including those that are private or protected) of a class must satisfy the constraints implied by the index members of the class as specified in section 3.9.4.

In the example

  1. class A {
  2. public x: number;
  3. public f() { }
  4. public g(a: any) { return undefined; }
  5. static s: string;
  6. }
  7. class B extends A {
  8. public y: number;
  9. public g(b: boolean) { return false; }
  10. }

the class type of ‘A’ is equivalent to

  1. interface A {
  2. x: number;
  3. f: () => void;
  4. g: (a: any) => any;
  5. }

and the class type of ‘B’ is equivalent to

  1. interface B {
  2. x: number;
  3. y: number;
  4. f: () => void;
  5. g: (b: boolean) => boolean;
  6. }

Note that static declarations in a class do not contribute to the class type—rather, static declarations introduce properties on the constructor function object. Also note that the declaration of ‘g’ in ‘B’ overrides the member inherited from ‘A’.

8.2.5 Constructor Function Types

The type of the constructor function introduced by a class declaration is called the constructor function type. The constructor function type has the following members:

  • If the class contains no constructor declaration and has no base class, a single construct signature with no parameters, having the same type parameters as the class (if any) and returning an instantiation of the class type with those type parameters passed as type arguments.
  • If the class contains no constructor declaration and has a base class, a set of construct signatures with the same parameters as those of the base class constructor function type following substitution of type parameters with the type arguments specified in the base class type reference, all having the same type parameters as the class (if any) and returning an instantiation of the class type with those type parameters passed as type arguments.
  • If the class contains a constructor declaration with no overloads, a construct signature with the parameter list of the constructor implementation, having the same type parameters as the class (if any) and returning an instantiation of the class type with those type parameters passed as type arguments.
  • If the class contains a constructor declaration with overloads, a set of construct signatures with the parameter lists of the overloads, all having the same type parameters as the class (if any) and returning an instantiation of the class type with those type parameters passed as type arguments.
  • A property for each static member variable declaration in the class body.
  • A property of a function type for each static member function declaration in the class body.
  • A property for each uniquely named static member accessor declaration in the class body.
  • A property named ‘prototype’, the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
  • All base class constructor function type properties that are not overridden in the class.

Every class automatically contains a static property member named ‘prototype’, the type of which is the containing class with type Any substituted for each type parameter.

The example

  1. class Pair<T1, T2> {
  2. constructor(public item1: T1, public item2: T2) { }
  3. }
  4. class TwoArrays<T> extends Pair<T[], T[]> { }

introduces two named types corresponding to

  1. interface Pair<T1, T2> {
  2. item1: T1;
  3. item2: T2;
  4. }
  5. interface TwoArrays<T> {
  6. item1: T[];
  7. item2: T[];
  8. }

and two constructor functions corresponding to

  1. var Pair: {
  2. new <T1, T2>(item1: T1, item2: T2): Pair<T1, T2>;
  3. }
  4. var TwoArrays: {
  5. new <T>(item1: T[], item2: T[]): TwoArrays<T>;
  6. }

Note that each construct signature in the constructor function types has the same type parameters as its class and returns an instantiation of its class with those type parameters passed as type arguments. Also note that when a derived class doesn’t declare a constructor, type arguments from the base class reference are substituted before construct signatures are propagated from the base constructor function type to the derived constructor function type.