TypeScript classes are JavaScript classes with type information and some compile-time modifiers. A class declares two things: a value, the constructor, and a type, its instances (Handbook: Classes).
Member modifiers
ClassMember:
{Decorator} {Modifier} Name [? | !] [: Type] [= Expression] ;
{Decorator} {Modifier} [get | set | *] Name [TypeParameters] ( Parameters ) [: Type] Block
{Modifier} [ Name : KeyType ] : Type ;
Modifier:
public | protected | private | static | abstract | override | readonly | declare | accessor | async
| Modifier | Effect | Output |
|---|---|---|
public | The default | Removed |
protected | Visible in this class and subclasses | Removed |
private | Visible in this class only | Removed |
#name | A JavaScript private field, enforced at run time | Kept |
readonly | Assignable only in the declaration and the constructor | Removed |
static | Belongs to the class | Kept |
abstract | No implementation; subclasses must provide one | Member removed |
override | Must override a base member | Removed |
declare | Declares a field’s type only | Field not written |
accessor | An automatic getter and setter (4.9) | Kept |
Access control
private and protected are checked only at compile time.
Element access with a string is not checked, so obj["x"] reaches a private
member, and at run time every such member is an ordinary property. A
#private field is real privacy, and it cannot be combined with an
accessibility modifier.
class A {
private x = 1;
protected y = 2;
#z = 3;
same(other: A) { return other.x + other.#z; } // fine: same class
}
class B extends A {
f(other: A, sibling: B) {
this.y; // fine
sibling.y; // fine
other.y; // error: must go through this class or a subclass
this.x; // error: private
}
}
const a = new A();
a.x; // error
a["x"]; // allowed: the escape hatch
A private or protected constructor limits who can create an
instance. A subclass of a class with a private constructor is an error. A subclass may
widen a protected member to public.
Parameter properties
Putting public, protected, private or
readonly on a constructor parameter declares a field with the same name and
assigns the parameter to it. The field’s initial value may be a default. A parameter
property is allowed only in a constructor implementation, not in an overload.
class Point {
constructor(public x: number, private readonly y = 1) {}
}
class Point {
x;
y;
constructor(x, y = 1) {
this.x = x;
this.y = y;
}
}
This generates code, so it is rejected by
erasableSyntaxOnly.
Fields
Under strictPropertyInitialization, every field must be initialised by a
declaration or a constructor. A field may be optional, may have undefined in
its type, or may use ! to assert that it is set elsewhere.
class Fields {
a: number; // error: not initialised
b: number = 1;
c?: number;
d!: number; // definite assignment
e: number | undefined; // allowed: includes undefined
f: number;
constructor() { this.f = 1; }
}
A declare field changes the type of an inherited field without writing a
new one. When useDefineForClassFields is on, which is the default for
target ES2022 and later, a field declaration without a value still creates
the property.
class Base { value: number | string = 1; }
class Sub extends Base { declare value: number; }
declare narrows the type and writes nothingSince 5.1 a get and set pair may have unrelated types if both
are annotated. Since 4.6 a constructor may run code before super(), as long
as that code does not use this.
Abstract classes
An abstract class cannot be created with new. Its abstract
members have no body and must be implemented by concrete subclasses. Abstract members are
allowed only in abstract classes.
abstract class Shape {
abstract area(): number;
abstract name: string;
log() { return this.area(); }
}
new Shape(); // error
class Square extends Shape {
name = "square";
area() { return 1; }
}
type Ctor = abstract new () => Shape;
const s: Ctor = Shape; // allowed
type Plain = new () => Shape;
const p: Plain = Shape; // error
abstract new accepts abstract classesoverride
override (4.3) states that a member replaces a member of the base class. It
is an error if the base has no such member. Under
noImplicitOverride
the modifier is required on every override.
implements
implements checks that the class is compatible with an interface or
object type, and does nothing else. Implementing an interface does not give the class’s
members any types: a method still needs its own parameter annotations, and an optional
property of the interface is not declared on the class.
interface Checkable { check(name: string): boolean; }
class NameChecker implements Checkable {
check(s) { return true; } // error: s is implicitly any
}
interface Sized { size?: number }
class Thing implements Sized {}
new Thing().size; // error: not declared on Thing
class Point { x = 1; y = 2; }
class Point3 implements Point { x = 1; y = 2; z = 3; } // a class can be used as an interface
implements is only a checkA class cannot implement a union type. An interface that extends a class with private members can only be implemented by that class or a subclass.
Index signatures
A class may declare an index signature, instance or static (4.3). Its members must then fit it, including methods.
class Store {
[key: string]: number | ((id: string) => number);
count = 1;
get(id: string) { return 1; }
}
this types
In a class or interface, this used as a type means the type of the current
instance, as seen from the subclass. It suits fluent methods.
class Builder {
add() { return this; }
}
class Styled extends Builder {
colour() { return this; }
}
new Styled().add().colour(); // add() returns Styled
this keeps the subclassMixins
A function may take a class and return a class that extends it. The base parameter must
have a constructor type with a rest parameter of type any[]
(Handbook:
Mixins).
type Constructor<T = {}> = new (...args: any[]) => T;
function Timestamped<TBase extends Constructor>(Base: TBase) {
return class extends Base {
time = Date.now();
};
}
class User { name = "Ada"; }
const Stamped = Timestamped(User);
new Stamped().time;
Classes can be generic: see Generics. A class can be decorated: see Decorators.