8.4 Property Member Declarations
Property member declarations can be member variable declarations, member function declarations, or member accessor declarations.
PropertyMemberDeclaration: MemberVariableDeclaration MemberFunctionDeclaration MemberAccessorDeclaration
Member declarations without a static
modifier are called instance member declarations. Instance property member declarations declare properties in the class type (section 8.2.4), and must specify names that are unique among all instance property member and parameter property declarations in the containing class, with the exception that instance get and set accessor declarations may pairwise specify the same name.
Member declarations with a static
modifier are called static member declarations. Static property member declarations declare properties in the constructor function type (section 8.2.5), and must specify names that are unique among all static property member declarations in the containing class, with the exception that static get and set accessor declarations may pairwise specify the same name.
Note that the declaration spaces of instance and static property members are separate. Thus, it is possible to have instance and static property members with the same name.
Except for overrides, as described in section 8.2.3, it is an error for a derived class to declare a property member with the same name and kind (instance or static) as a base class member.
Every class automatically contains a static property member 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. It is an error to explicitly declare a static property member with the name ‘prototype’.
Below is an example of a class containing both instance and static property member declarations:
class Point {
constructor(public x: number, public y: number) { }
public distance(p: Point) {
var dx = this.x - p.x;
var dy = this.y - p.y;
return Math.sqrt(dx * dx + dy * dy);
}
static origin = new Point(0, 0);
static distance(p1: Point, p2: Point) { return p1.distance(p2); }
}
The class type ‘Point’ has the members:
interface Point {
x: number;
y: number;
distance(p: Point);
}
and the constructor function ‘Point’ has a type corresponding to the declaration:
var Point: {
new(x: number, y: number): Point;
origin: Point;
distance(p1: Point, p2: Point): number;
}
8.4.1 Member Variable Declarations
A member variable declaration declares an instance member variable or a static member variable.
MemberVariableDeclaration: AccessibilityModifieropt static
opt PropertyName TypeAnnotationopt Initializeropt ;
The type associated with a member variable declaration is determined in the same manner as an ordinary variable declaration (see section 5.2).
An instance member variable declaration introduces a member in the class type and optionally initializes a property on instances of the class. Initializers in instance member variable declarations are executed once for every new instance of the class and are equivalent to assignments to properties of this
in the constructor. In an initializer expression for an instance member variable, this
is of the this-type (section 3.6.3) of the class.
A static member variable declaration introduces a property in the constructor function type and optionally initializes a property on the constructor function object. Initializers in static member variable declarations are executed once when the containing script or module is loaded.
Initializer expressions for instance member variables are evaluated in the scope of the class constructor body but are not permitted to reference parameters or local variables of the constructor. This effectively means that entities from outer scopes by the same name as a constructor parameter or local variable are inaccessible in initializer expressions for instance member variables.
Since instance member variable initializers are equivalent to assignments to properties of this
in the constructor, the example
class Employee {
public name: string;
public address: string;
public retired = false;
public manager: Employee = null;
public reports: Employee[] = [];
}
is equivalent to
class Employee {
public name: string;
public address: string;
public retired: boolean;
public manager: Employee;
public reports: Employee[];
constructor() {
this.retired = false;
this.manager = null;
this.reports = [];
}
}
8.4.2 Member Function Declarations
A member function declaration declares an instance member function or a static member function.
MemberFunctionDeclaration: AccessibilityModifieropt static
opt PropertyName CallSignature {
FunctionBody }
AccessibilityModifieropt static
opt PropertyName CallSignature ;
A member function declaration is processed in the same manner as an ordinary function declaration (section 6), except that in a member function this
has a known type.
All declarations for the same member function must specify the same accessibility (public, private, or protected) and kind (instance or static).
An instance member function declaration declares a property in the class type and assigns a function object to a property on the prototype object of the class. In the body of an instance member function declaration, this
is of the this-type (section 3.6.3) of the class.
A static member function declaration declares a property in the constructor function type and assigns a function object to a property on the constructor function object. In the body of a static member function declaration, the type of this
is the constructor function type.
A member function can access overridden base class members using a super property access (section 4.9.2). For example
class Point {
constructor(public x: number, public y: number) { }
public toString() {
return "x=" + this.x + " y=" + this.y;
}
}
class ColoredPoint extends Point {
constructor(x: number, y: number, public color: string) {
super(x, y);
}
public toString() {
return super.toString() + " color=" + this.color;
}
}
In a static member function, this
represents the constructor function object on which the static member function was invoked. Thus, a call to ‘new this()’ may actually invoke a derived class constructor:
class A {
a = 1;
static create() {
return new this();
}
}
class B extends A {
b = 2;
}
var x = A.create(); // new A()
var y = B.create(); // new B()
Note that TypeScript doesn’t require or verify that derived constructor functions are subtypes of base constructor functions. In other words, changing the declaration of ‘B’ to
class B extends A {
constructor(public b: number) {
super();
}
}
does not cause errors in the example, even though the call to the constructor from the ‘create’ function doesn’t specify an argument (thus giving the value ‘undefined’ to ‘b’).
8.4.3 Member Accessor Declarations
A member accessor declaration declares an instance member accessor or a static member accessor.
MemberAccessorDeclaration: AccessibilityModifieropt static
opt GetAccessor AccessibilityModifieropt static
opt SetAccessor
Get and set accessors are processed in the same manner as in an object literal (section 4.5), except that a contextual type is never available in a member accessor declaration.
Accessors for the same member name must specify the same accessibility.
An instance member accessor declaration declares a property in the class type and defines a property on the prototype object of the class with a get or set accessor. In the body of an instance member accessor declaration, this
is of the this-type (section 3.6.3) of the class.
A static member accessor declaration declares a property in the constructor function type and defines a property on the constructor function object of the class with a get or set accessor. In the body of a static member accessor declaration, the type of this
is the constructor function type.
Get and set accessors are emitted as calls to ‘Object.defineProperty’ in the generated JavaScript, as described in section 8.7.1.
8.4.4 Dynamic Property Declarations
If the PropertyName of a property member declaration is a computed property name that doesn’t denote a well-known symbol (2.2.3), the construct is considered a dynamic property declaration. The following rules apply to dynamic property declarations:
- A dynamic property declaration does not introduce a property in the class type or constructor function type.
- The property name expression of a dynamic property assignment must be of type Any or the String, Number, or Symbol primitive type.
- The name associated with a dynamic property declarations is considered to be a numeric property name if the property name expression is of type Any or the Number primitive type.