Class
Structure
/*
`extends` tells User is a sub-class of Account. (Only extends ONE class)
`implements` ensures that User comforms to these `interfaces` or `types`.
*/
class User extends Account implements Updatable, Serializable {
// The default property being public access, not optional and writable.
id: string;
// Defines a optional property, which can hold `undefined` or not exist at all.
middleName?: string;
/*
Defines a `trust me, it's there` property.
(Enforcing to the compiler that this cannot be optional)
*/
name!: string;
/*
Defines private properties, only accessible to current class.
*/
private attr: unknown; // Private only at compilation
#attr: unknown; // Private at compilation and runtime
// Defines a property with a default value.
role = "Student";
/*
Defines a readonly property.
Can only be set here at declaration or at the constructor.
*/
readonly createdAt: Date;
// See more at `constructor sections` bellow.
constructor() { ... }
/*
Describe class methods.
(Prefer using `arrow function` style to not impact the use of `this`)
More info bellow.
*/
setName(name: string) { this.name = name; }
checkName = (name: string) => { return this.name; }
// Overload method definitions
sync(): void;
sync(param: string): string;
// Getter and Setter of properties
get role() { return this.role.setUpperCase(); }
set role(value: "Student" | "Teacher") { this.role = value.setLowerCase(); }
/*
Make `private` or `protected` methods.
(`protected` are accessible to sub-classes)
*/
private makeRequest() { ... }
protected makeRequest() { ... }
// Define `static` properties or methods
static #userCount = 0; // static and private
static registerUser(user: User) { ... }
/*
Static blocks for setting up static variables.
(`this` refers to the static class)
*/
static {
this.#userCount = -1;
}
}constructor section
constructor sectionYou could instead of declaring properties at the top, declare them at constructor's parameters section.
Or inside constructor section. But like this, you cannot assign visibility and other modifiers.
These properties would be declared as default ones. (public, not optional and writable)
And you must provide a value.
this in classes
this in classesThe value of this inside a function depends on how the function is called or defined.
It is not garanteed to always be the class instance.
This problem is refered to as (losing this context).
Read more on .
Defining methods with method() {}:
Declaring methods like this may implicate that the this context is lost and refers to another execution context, leading to runtime errors.
This happens on specific occasions like:
Passing the class method as Callback or storing it in a variable.
Using
thisin Event Listeners or Callbacks.
Defining methods with arrow functions:
Using arrow functions when declaring methods in classes is a good way to enforce that this will refer to the method's Class.
Since they only inherit the this from their enclosing lexical scope.
Declaring methods with arrow functions have a trade off.
Each instance of Person now has its own copy of the method, which increases memory usage, and could have an impact if the class will have a large number of instances.
Binding this with .bind():
An alternative approach is to explicitly bind this using .bind(), allowing you to control this reference without having to use arrow functions.
Abstract classes
When declaring classes as not implementable, but as existing to be subclassed in the type system.
You dont instanciate an absctract class.
Can have absctract methods.
Difference of Abstract class and Interface
Abstract classes can have partial implementations. You can code inside them.
Interfaces cannot have code in them, they only describe typings and method names (Template Methods).
Decorators and Attributes
You can use decorators on classes, class methods, accessors, properties and parameters to methods.
Last updated