TypeScript discrete notes

Anh-Thi Dinh
Documentation
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.
type vs interface (official doc)
  • Very similar, some cases → choose one of 2 → the same!
  • Almost all features in interface are available in type
  • Key distinction: type cannot be re-opened to add new properties vs interface is extendable!
any vs unknown (Source)
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']
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à AB 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