Documentation
- TypeScript Deep Dive — The definitive guide to TypeScript and possibly the best TypeScript book
- Write doc as comment for functions in TypeScript → https://tsdoc.org/ → playground (interactive)
Inheritance and extends (Official doc)
A class can reused the properties and methods of the base class.
1class Animal {
2 move() {
3 console.log("Moving along!");
4 }
5}
6
7class Dog extends Animal {
8 woof(times: number) {
9 for (let i = 0; i < times; i++) {
10 console.log("woof!");
11 }
12 }
13}
14
15const d = new Dog();
16// Base class method
17d.move();
18// Derived class method
19d.woof(3);
1type TypeValueDico<KeyType extends string, ValueType> = {
2 [key in KeyType]: ValueType;
3};
4
5const dicoValues: TypeValueDico<string, string | boolean>;
6
7// then
8dicoValues = { [string]: string }
9// or
10dicoValues = { [string]: boolean }
protected
, private
, public
, readonly
, static
private
= can be accessed only within the class and even their sub-classes won't be allowed to use their private properties and attributes
public
= By default, all members of a class in TypeScript are public. All the public members can be accessed anywhere without any restrictions.
- Very similar, some cases → choose one of 2 → the same!
- Almost all features in
interface
are available intype
- Key distinction:
type
cannot be re-opened to add new properties vsinterface
is extendable!
1let vAny: any = 10; // We can assign anything to any
2let vUnknown: unknown = 10; // We can assign anything to unknown just like any
3
4
5let s1: string = vAny; // Any is assignable to anything
6let s2: string = vUnknown; // Invalid; we can't assign vUnknown to any other type (without an explicit assertion)
7
8vAny.method(); // Ok; anything goes with any
9vUnknown.method(); // Not ok; we don't know anything about this variable
Get types from arrays
1const animals = ['cat', 'dog', 'mouse'] as const
2type Animal = typeof animals[number]
3
4// type Animal = 'cat' | 'dog' | 'mouse'
Other ways → using
enum
👇 Source (there are more in that page)1// ✅ For STRING Enums
2enum StringEnum {
3 Small = 'S',
4 Medium = 'M',
5 Large = 'L',
6}
7const values = Object.values(StringEnum);// ['S', 'M', 'L']
8const names = Object.keys(StringEnum); // ['Small', 'Medium', 'Large']
1// ✅ For NUMERIC Enums
2enum NumericEnum {
3 Small,
4 Medium,
5 Large,
6}
7const values = Object.keys(NumericEnum).filter((v) => !isNaN(Number(v)));
8// ['0', '1', '2']
9const names = Object.keys(NumericEnum).filter((v) => isNaN(Number(v)));
10// ['Small', 'Medium', 'Large']
Enum (official doc)
1enum LogLevel {
2 ERROR,
3 WARN,
4 INFO,
5 DEBUG,
6}
7
8/**
9 * This is equivalent to:
10 * type LogLevelStrings = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
11 */
12type LogLevelStrings = keyof typeof LogLevel;
Type
T
<T>
(a type variable) → Generics / type variable : nếu we use any
, chúng ta không biết function returns type gì?This
T
allows us to capture the type the user provides → use this info later!1// declare
2function identity<T>(arg: T): T {return arg;}
3
4// 1st use (explicit) -> RECOMMEND!!!
5let output = identity<string>("myString");
6// ^ = let output: string
7
8// 2nd use (implicit) -> not recommend (in a complex situation)
9let output = identity("myString");
10// ^ = let output: string
Union types (
varName: A | B
)Lưu ý là
A
và B
không thể ở dạng boolean | object
được! Chúng có thể là {a:boolean} | {x: string}
1// Obj1 has "message" but Obj2
2const getText = (obj: Obj1 | Obj2): string => {
3 if ("message" in obj) {
4 return obj.message
5 }
6
7 return obj.text
8}
1type A = 'a1' | 'a2'
2type B = 'b1' | 'b2'
3type C = A | B // <=> type C = 'a1' | 'a2' | 'b1' | 'b2'
key in
, keyof
1type A = 'a' | 'b'
2type B = { [key in A]: boolean }
3// type B = { a: boolean, b: boolean }
4
5type A = { a: string, b: boolean }
6type B = { [key in keyof A]: boolean }
7// type B = { a: boolean, b: boolean }
1enum CLAUDE_MODELS {
2 'a' = 'Claude 3 Opus',
3 'b' = 'Claude 3.5 Sonnet',
4 'c' = 'Claude 3 Sonnet'
5}
6
7type ClaudeModelKeys = keyof typeof CLAUDE_MODELS;
8// ClaudeModelKeys = 'a' | 'b' | 'c'
constructor
1class User {
2 private name: string;
3 private surname: string;
4
5 constructor(name: string, surname: string) {
6 this.name = name;
7 this.surname = surname;
8 }
9}
1// shorthand
2class User {
3 constructor(
4 private name: string,
5 private surname: string,
6 private age: number
7 ) {}
8}
9
10// you can apply for "public", "protected" also
Both will produce the same thing,
1var User = /** @class */ (function() {
2 function User(name, surname, age) {
3 this.name = name;
4 this.surname = surname;
5 this.age = age;
6 }
7 return User;
8})();
Static member (official doc)
1class MyClass {
2 static x = 0;
3 static printX() {
4 console.log(MyClass.x);
5 }
6}
7console.log(MyClass.x);
8MyClass.printX();
Troubleshooting