📖 TypeScript Mastery - Advanced TypeScript Patterns và Performance
80 phút

Advanced TypeScript Patterns và Performance

Decorators và Metadata

Class Decorators

function LogClass(target: Function) {
  console.log(`Class ${target.name} was defined`);
}

function Entity(tableName: string) {
  return function<T extends { new(...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
      public readonly tableName = tableName;
    };
  };
}

@LogClass
@Entity('users')
class User {
  constructor(public name: string, public email: string) {}
}

const user = new User('John', 'john@example.com');
console.log((user as any).tableName); // 'users'

Method Decorators

function LogMethod(
  target: any,
  propertyName: string,
  descriptor: PropertyDescriptor
) {
  const originalMethod = descriptor.value;
  
  descriptor.value = function(...args: any[]) {
    console.log(`Calling ${propertyName} with args:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`${propertyName} returned:`, result);
    return result;
  };
  
  return descriptor;
}

class Calculator {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

Property Decorators

function MinLength(length: number) {
  return function(target: any, propertyName: string) {
    let value: string;
    
    const getter = () => value;
    const setter = (newValue: string) => {
      if (newValue.length < length) {
        throw new Error(
          `${propertyName} must be at least ${length} characters long`
        );
      }
      value = newValue;
    };
    
    Object.defineProperty(target, propertyName, {
      get: getter,
      set: setter
    });
  };
}

class User {
  @MinLength(3)
  username: string;
  
  constructor(username: string) {
    this.username = username;
  }
}

Mixins

Mixin Pattern

type Constructor<T = {}> = new (...args: any[]) => T;

function Timestamped<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    timestamp = new Date();
  };
}

function Activatable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    isActive = false;
    
    activate() {
      this.isActive = true;
    }
    
    deactivate() {
      this.isActive = false;
    }
  };
}

class User {
  constructor(public name: string) {}
}

const TimestampedActivatableUser = Timestamped(Activatable(User));
const user = new TimestampedActivatableUser('John');
user.activate();
console.log(user.timestamp, user.isActive);

Performance Optimization

const assertions

// Thay vì
const colors = ['red', 'green', 'blue']; // string[]

// Sử dụng const assertions
const colors = ['red', 'green', 'blue'] as const; // readonly ["red", "green", "blue"]

// Objects với const assertions
const user = {
  name: 'John',
  age: 30,
  permissions: ['read', 'write']
} as const;

// user.name = 'Jane'; // Error!

Satisfies Operator

interface Config {
  color: 'red' | 'green' | 'blue';
  size: 'small' | 'medium' | 'large';
}

const config = {
  color: 'red',
  size: 'medium'
} satisfies Config;

// TypeScript biết config.color là 'red' | 'green' | 'blue'
// nhưng vẫn giữ literal type 'red'

Template Literal Types Performance

// Có thể gây performance issues với types phức tạp
type Color = 'red' | 'green' | 'blue';
type Size = 'small' | 'medium' | 'large';

// Tốt
type ButtonVariant = `${Color}-${Size}`;

// Có thể gây issues
// type AllCombinations = `${Color}-${Size}-${Variant}...`;

Advanced Conditional Types

Recursive Types

type JsonValue = 
  | string
  | number
  | boolean
  | null
  | JsonValue[]
  | { [key: string]: JsonValue };

type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object 
    ? DeepReadonly<T[P]>
    : T[P];
};

type DeepRequired<T> = {
  [P in keyof T]-?: T[P] extends object 
    ? DeepRequired<T[P]>
    : T[P];
};

Template Literal Types Manipulation

type EventName = 'click' | 'scroll' | 'keypress';
type HandlerName<T extends string> = `on${Capitalize<T>}`;

type EventHandlers = {
  [K in EventName as HandlerName<K>]: (event: Event) => void;
};
// {
//   onClick: (event: Event) => void;
//   onScroll: (event: Event) => void;
//   onKeypress: (event: Event) => void;
// }

// Advanced manipulation
type GetterName<T extends string> = `get${Capitalize<T>}`;
type SetterName<T extends string> = `set${Capitalize<T>}`;

type Accessors<T extends string> = 
  | GetterName<T> 
  | SetterName<T>;

Type-Level Programming

Type-Level Arithmetic

type Length<T extends any[]> = T['length'];

type BuildArray<
  N extends number, 
  T extends any[] = []
> = T['length'] extends N 
  ? T 
  : BuildArray<N, [...T, any]>;

type Add<A extends number, B extends number> = 
  Length<[...BuildArray<A>, ...BuildArray<B>]>;

type Subtract<A extends number, B extends number> = 
  BuildArray<A> extends [...BuildArray<B>, ...infer R] 
    ? Length<R> 
    : never;

type Result1 = Add<5, 3>; // 8
type Result2 = Subtract<8, 3>; // 5

String Manipulation ở Type Level

type Split<
  S extends string, 
  D extends string
> = S extends `${infer T}${D}${infer U}`
  ? [T, ...Split<U, D>]
  : [S];

type Join<
  T extends string[], 
  D extends string
> = T extends [infer F, ...infer R]
  ? R extends string[]
    ? F extends string
      ? `${F}${D}${Join<R, D>}`
      : never
    : F
  : '';

type Path = 'users/123/profile';
type Parts = Split<Path, '/'>; // ['users', '123', 'profile']
type Reconstructed = Join<Parts, '-'>; // 'users-123-profile'

Compiler Performance

Project References

// tsconfig.json
{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true
  },
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/utils" }
  ]
}

Incremental Builds

{
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": "./.tsbuildinfo"
  }
}

Skip Lib Check khi có thể

{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

📝 Bài tập (1)

  1. Xây dựng type-safe ORM với advanced TypeScript features

Bài học "Advanced TypeScript Patterns và Performance" - Khóa học "TypeScript Mastery"