- class fields (≙ instance properties) types are declared outside of constructor, matches syntax of classical languages, not needed for inherited properties
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Person {
constructor(name) {
this.name = name;
}
}
- can leave out constructor if initialises with value
class Person {
name = "Peter";
}
class Person {
constructor() {
this.name = "Peter";
}
}
- can limit accessibility of properties and methods by prefixing with modifiers, but only applies within TS, gets stripped away with compilation ❗️
public
: property is available inside and of outside class, like default JS
private
: property is available only inside class, if makes constructor itself private the class can not be instantiated outside or extended
beware: even though behaves like #
within TS, doesn’t compile to #
in JS ❗️
protected
: like private
, but allows use in derived classes, if protects constructor itself the class can not be instantiated outside but extended
readonly
: property can be written to only from within constructor, not other method or outside, but can still be read from outside
class Person {
public name: string;
constructor(name: string) {
this.name = name;
}
}
class Person {
constructor(name) {
this.name = name;
}
}
- parameter properties: instance property shorthand by prefixing constructor parameter directly with any of the modifiers, makes type of class field outside of constructor obsolete
class Person {
constructor(public name: string) {
}
}
class Person {
constructor(name) {
this.name = name;
}
}
static
properties can be used with same modifiers, but not use a type parameter from a generic class
class Person {
static fullname = "Peter";
}
class Person {}
Person.fullname = "Peter";
- constructors themselves can not be generics or have return types
- can specify overloads for constructor
- use
strictPropertyInitialization
flag to demand initialisation of class fields to not forget
- use definite assignment assertion operator
!
after field name to assert it will be initialised, e.g. through calling some method
- a class automatically creates a type representing the classes’ instances, i.e. can use like interfaces, type aliases, etc.
- two classes containing identical private or protected properties are not compatible types
class Person {
constructor(private name: string) {
}
}
class Employee {
constructor (private name: string) {
}
}
const p: Employee = new Person("Peter");
- a getter without a setter is automatically inferred to be
readonly
- the getter type must be a subtype of the setter type
Inheriting classes
- use
implements
to check that a class instance implements a type
- can implement multiple types, separated by comma or after each other
- doesn’t change class at all, just error checking, don’t confuse with
extends
❗️
interface Named {
name: string;
}
class Person implements Named {
name = "Peter";
}
class Car implements Named {
speed = 42;
}
- beware: only checks against class instance, i.e. can’t check if implements given static properties or constructor ❗
- can implement constructor check using class expressions
interface Named {
name: string;
}
interface PersonConstructor {
new (name: string): void;
}
const Person: PersonConstructor = class Person implements Named {
name: string;
constructor(name: string) {
this.name = name;
}
}
- can use together with
extends
, first extends
then implements
- use
override
on a method in child class to guarantee that it exists in parent class, doesn’t add new one if doesn’t exist, e.g. after rename, after deleted, etc.
class Parent {
}
class Child extends Parent {
override foo() {}
}
Abstract classes
- template classes, can not be instantiated, only extended
- use
abstract
keyword before class
keyword
- can contain abstract properties without implementation, prepend
abstract
keyword
- can contain “concrete” properties with implementation
- abstract class is compiled to normal class, abstract properties are removed
- like an interface that is implemented, but unlike interface it is compiled to JS with the “concrete” properties
- like parent class with protected constructor, but can also contain abstract properties
abstract class Animal {
abstract eat(): void;
}
class Lion extends Animal {
eat() { console.log("Feeding...") }
growl() { console.log("Grrrr...") }
}
class Goat extends Animal {
maeh() { console.log("Maehhh...") }
}
const x = new Animal();
const y = new Lion();