class Point {}
➡️Class fields
A field declaration creates a public writeable property on a class:
class Point {
x: number;
y: number;
}
const pt = new Point();
pt.x = 0;
pt.y = 0;
As with other locations, the type annotation is optional, but will be an implicit any if not specified.
Fields can also have initializers; these will run automatically when the class is instantiated:
class Point {
x = 0;
y = 0;
}
const pt = new Point();
// Prints 0, 0
console.log(`${pt.x}, ${pt.y}`);
Just like with const, let, and var, the initializer of a class property will be used to infer its type:
const pt = new Point();
pt.x = "0"; //Error ==> Type 'string' is
//not assignable to type 'number'.
🔵 read-only fields
Fields may be prefixed with the readonly modifier. This prevents assignments to the field outside of the constructor.
class Greeter {
readonly name: string = "world";
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName;
}
}
err() {
this.name = "not ok"; //Cannot assign to
//'name' because it is a read-only property.
}
}
const g = new Greeter();
g.name = "also not ok"; //Error -
//Cannot assign to 'name' because it is a read-only property.
➡️ Constructors
Class constructors are very similar to functions. You can add parameters with type annotations, default values, and overloads:
class Point {
x: number;
y: number;
// Normal signature with defaults
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
There are just a few differences between class constructor signatures and function signatures:
- Constructors can’t have type parameters - these belong on the outer class declaration, which we’ll learn about later
class Point{
constructor(val:T) //Error Type T is not defined
{
}
}
class Point<T>{
constructor(val:T) //Ok
{
}
}
const point = new Point<number>(10)
- Constructors can’t have return type annotations - the class instance type is always what’s returned.
class Point{
constructor():boolean //Error - Type annotation
//cannot appear on a constructor declaration
{
}
}
➡️ Methods
A function property on a class is called a method. Methods can use all the same type annotations as functions and constructors:
class Point {
x = 10;
y = 10;
scale(n: number): void {
this.x *= n;
this.y *= n;
}
}
Note that inside a method body, it is still mandatory to access fields and other methods via this
let x: number = 0;
class C {
x: string = "hello";
m() {
// This is trying to modify 'x' from line 1, not the class property
x = "world";
}
}
➡️ Class Heritage
🔵 implements Clauses
You can use an implements clause to check that a class satisfies a particular interface. An error will be issued if a class fails to correctly implement it:
interface Pingable {
ping(): void;
}
class Sonar implements Pingable {
ping() {
console.log("ping!");
}
}
class Ball implements Pingable { //Error - Class 'Ball' incorrectly
//implements interface 'Pingable'. Property 'ping' is missing
//in type 'Ball' but required in type 'Pingable'.
pong() {
console.log("pong!");
}
}
Classes may also implement multiple interfaces, e.g. class C implements A, B {.
🚨 caution -
It’s important to understand that an implements clause is only a check that the class can be treated as the interface type. It doesn’t change the type of the class or its methods at all. A common source of error is to assume that an implements clause will change the class type - it doesn’t!
interface Checkable {
check(name: string): boolean;
}
class NameChecker implements Checkable {
check(s) { //warning ==> Parameter 's' implicitly has an 'any' type.
// Notice no error here because type is 'any'
return s.toLowerCase() === "ok";
}
}
In this example, we perhaps expected that s’s type would be influenced by the name: string parameter of check. It is not - implements clauses don’t change how the class body is checked or its type inferred.
similarly, implementing an interface with an optional property doesn’t create that property:
interface A {
x: number;
y?: number;
}
class C implements A {
x = 0;
}
const c = new C();
c.y = 10;
🔵 extends Clauses
Classes may extend from a base class. A derived class has all the properties and methods of its base class, and can also define additional members.
class Animal {
move() {
console.log("Moving along!");
}
}
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
console.log("woof!");
}
}
}
const d = new Dog();
// Base class method
d.move();
// Derived class method
d.woof(3);
➡️ Member Visibility
🔵public
The default visibility of class members is public. A public member can be accessed anywhere:
class Greeter {
public greet() {
console.log("hi!");
}
}
const g = new Greeter();
g.greet();
Because public is already the default visibility modifier, you don’t ever need to write it on a class member, but might choose to do so for style/readability reasons.
🔵protected
protected members are only visible to subclasses of the class they’re declared in.
class Greeter {
public greet() {
console.log("Hello, " + this.getName());
}
protected getName() {
return "hi";
}
}
class SpecialGreeter extends Greeter {
public howdy() {
// OK to access protected member here
console.log("Howdy, " + this.getName());
}
}
const g = new SpecialGreeter();
g.greet(); // OK
g.getName(); //Error - Property 'getName' is protected and only
//accessible within class 'Greeter' and its subclasses.
🔵sibling protected members
TypeScript doesn’t allow accessing protected members of a sibling class in a class hierarchy:
class Base {
protected x: number = 1;
}
class Derived1 extends Base {
protected x: number = 5;
}
class Derived2 extends Base {
f1(other: Derived2) {
other.x = 10;
}
f2(other: Derived1) {
other.x = 10; //Error - Property 'x' is protected
//and only accessible within class 'Derived1' and its subclasses.
}
}
🔵private
private is like protected , but doesn’t allow access to the member even from subclasses:
class Base {
private x = 0;
}
const b = new Base();
// Can't access from outside the class
console.log(b.x); // Error -Property 'x' is private and
//only accessible within class 'Base'.
🚨 Caveats
Typescript private and protected access modifiers only exists in typescript not in JavaScript. meaning that if you run the script with access error the script will run ok.
class A{
private sayHi()
{
console.log("private method");
}
}
const a = new A();
//during compilation error occurs
a.sayHi(); // Error - Property sayHi is private and only
//accessible within class 'A'.
//But if we execute the file it gives below output -
//private method
🚨 JavaScript supports private access modifier but syntax is different from those of TypeScript.
class A{
#sayHi()
{
console.log("private method");
}
}
const a = new A();
a.sayHi(); //Error - a.sayHi is not a function
🚨 You can access the private members of class outside of the class with bracket [ ] syntax
class A{
private sceret = "Hello"
}
const a = new A();
a["sceret"]; // Hello
➡️ Static Fields and methods
Classes may have static members. These members aren’t associated with a particular instance of the class. They can be accessed through the class constructor object itself:
class MyClass {
static x = 0;
static printX() {
console.log(MyClass.x);
}
}
console.log(MyClass.x);
MyClass.printX();
Static members can also use the same public, protected, and private visibility modifiers:
class MyClass {
private static x = 0;
}
console.log(MyClass.x); //Error - Property 'x' is private
//and only accessible within class 'MyClass'.
Static members are also inherited:
class Base {
static getGreeting() {
return "Hello world";
}
}
class Derived extends Base {
myGreeting = Derived.getGreeting(); //Hello world
}
➡️ Generic Classes
Classes, much like interfaces, can be generic. When a generic class is instantiated with new, its type parameters are inferred the same way as in a function call:
class Box<Type> {
contents: Type;
constructor(value: Type) {
this.contents = value;
}
}
const b = new Box("hello!"); //Infered as const b: Box<string>
Type Parameters in Static Members
type parameters does ❌ not supported in static methods
class Box<Type> {
static defaultValue: Type; //Error -Static members cannot
//reference class type parameters.
}
➡️ Parameter Properties
TypeScript offers special syntax for turning a constructor parameter into a class property with the same name and value. These are called parameter properties and are created by prefixing a constructor argument with one of the visibility modifiers public, private, protected, or read-only. The resulting field gets those modifier(s):
class Params {
constructor(
public readonly x: number,
protected y: number,
private z: number
) {
// No body necessary
}
}
const a = new Params(1, 2, 3);
console.log(a.x); //1
console.log(a.z); //Error -Property 'z' is private
//and only accessible within class 'Params'.
➡️ abstract Classes and Members
Classes, methods, and fields in TypeScript may be abstract.
An abstract method or abstract field is one that hasn’t had an implementation provided. These members must exist inside an abstract class, which cannot be directly instantiated.
The role of abstract classes is to serve as a base class for subclasses which do implement all the abstract members. When a class doesn’t have any abstract members, it is said to be concrete.
abstract class Base {
abstract getName(): string;
printName() {
console.log("Hello, " + this.getName());
}
}
const b = new Base(); //Error - Cannot create
//an instance of an abstract class.
We can’t instantiate Base with new because it’s abstract. Instead, we need to make a derived class and implement the abstract members:
class Derived extends Base {
getName() {
return "world";
}
}
const d = new Derived();
d.printName(); //Ok
Notice that if we forget to implement the base class’s abstract members, we’ll get an error:
class Derived extends Base {//Error - Non-abstract class
//'Derived' does not implement inherited abstract member
//getName from class 'Base'.
}
🚨🚨 Things to note -
- abstract keyword used to mark a class abstract.
- only abstract classes can have abstract methods and fields. Normal classes cannot have theme.
- If a class is extends abstract class then it have to implement all the abstract methods and fields of that abstract class.
extends and implements in abstract classes
implements -
there is no ❌ use implements in a abstract classes as implements is a indication to implement the methods and properties of interface or type and that is against what abstract classes are about.
still use can use implements on a abstract class and then you have to compulsory declare those in a abstract class.
class A {
hello;
sayHi(){
}
}
abstract class B implements A{
hello;
sayHi:boolean;
abstract sayBye():void
}```
Top comments (26)
YUJ
dfgfd
sefd
FGH
ui
T13
fsdf
WERT
dfgfd sfsdfsd
RGd
sdfds
tyt
fdgdgfdfgdf
xvd
asasd
RG
ERER
gv
ty