typescript-handbook笔记

/post/ts-note article cover image

基础类型

注解

通过注解指定变量类型

ts
const name: string = 'alice';
const age: number = 17;

元祖

具有固定长度和属性的数组,通常用来表示相关联的属性

ts
const info: [string, number] = ['alice', 17];

Enumms

用来表示一组常量,其默认值从0开始当指定值后会顺延递增

ts
enum Size { Small = 1, Medium, Large }

Functions

typescript中函数的使用, 接收一个数字类型并返回一个数字类型

ts
function getAmount(count: number): number {
	return count ** 0.3;
}

Objects

typescript中对象的复合使用

ts
const info: {
  name: string;
  total: number;
  record: (date: Date) => void
} = {
	name: 'asd',
	total: 20,
	record: (date: Date) => {}
}

高级类型

类型别名

ts
type person = {
  name: string;
  age: number;
  sleep: (date: Date) => void;
}

联合类型

ts
let weight: number | string = 1;
weight = '1kg';

交叉类型

ts
type UIWidget = Draggable & Droppable;

字面量类型

ts
type Quantity = 50 | 100;

可空值类型

ts
let name: string | null = null;

可选链(?.)

ts
customer?.birthdate?.getFullYear();
customers?.[0];
log?.('message');

空值合并操作符

ts
someValue ?? 30;

类型断言

ts
obj as Person;

未知类型

ts
function render(document: unkown) {
  // 在调用未知类型前,我们必须缩小一个具体的范围
  // 一般使用类型守卫
  if (typeof document === 'string') {
    // ...
  }
}

永不类型

ts
function processEvents(): never {
  // 因为它是无限循环所以永远不回返回什么
  while(true) {
    // ...
  }
}

类和接口

类和构造函数

ts
class Account {
  id: number;
  constructor(id: number) {
    this.id = id;
  }
  deposit() {
    // ...
  }
}

const account = new Account(1);

account.id = 1;
account.deposit();

访问修饰符

ts
class Account {
  private _balance: number;
	// 保护成员可被继承,私有却不行
  protected _taxRate: number;
}

参数属性

ts
class Account {
  // ts4.x新增写法,在构造函数中创建并初始化省略属性声明
  constructor(public id: number, private balance: number) {
  }
}

getters和setters

ts
class Account {
  private _balance = 0;

  get balance(): number {
    return this._balance;
  }

  set balance(val: number) {
    if (val < 0) return null;
    this._balance = val;
  }
}

索引签名

ts
class SeatAssignment {
  // 使用索引签名可以动态为对象添加属性而不失去类型安全
  [seatNumber: string]: string
}

const seats = new SeatAssignment();
seats.A1 = 'aaa';
seats.A2 = 'bbb';

静态成员

ts
class Ride {
  static activeRides = 0;
}

Ride.activeRides++;

方法覆盖

ts
class Student extends Person {
  override speak() {
    console.log('Student speaking');
  }
}

抽象类

ts
abstract class Shape {
  // 抽象类方法没有方法体
  abstract render();
}

class Circle extends Shape {
  override render() {
    console.log('rendering a circle');
  }
}

接口

ts
interface Calendar {
  name: string;
  addEvent(): viod;
}

class GoogleCalendar implements Calendar {
  // ...
}

范型

相对于单个的单一类型,范型用来创建可复用、可扩展、灵活的组件(类、接口、方法)

ts
// 范型在尖括号中使用一个或多个参数来表示
class KeyValuePair<T, U> {
  constructor(public key: T, public val: U) {}
}

// 当使用范型时,应当为参数应用类型以供编译器进行推断
let pair = new KeyValuePair<number, string>(1, 'a');

使用extend关键词对范型进行约束和扩展

ts
// 约束范型
function echo<T extends number | string>(value: T) {}

// 扩展范型

// 通过集成派生出包含父类的类型
class CompressibleStore<T> extends Store<T> {}

// 约束扩展
class SearchableStore<T extends {name: string}> extends Store<T> {}

// 固定类型
class ProductStore extends Store<Product> {}

使用keyof关键词从所给对象产出联合类型

ts
interface Product {
  name: string
  price: number
}

let someGood: keyof Product;
// same as
let someGood: 'name' | 'price';

类型映射

基于现有类型创建新类型,并对这些属性进行某种约束和操作

ts
type ReadOnly<T> = {
  readonly [K in keyof T]: T[K]
}

type Optional<T> = {
  readonly [K in keyof T]?: T[K]
}

type Nullable<T> = {
  [K in keyof T]: T[K] | null
}

官方提供了很多基于范型组合的工具类型 Utility Types 以供方便使用

装饰器

装饰器提供了一种为类声明和成员(properties、methods、parameters、getters、setters)添加注释和元编程语法的实验性功能.

详细资料: A Complete Guide to TypeScript Decorators

json
// 开启选项
{
  "complierOptions": {
    "target": "ES5",
    "experimentalDecorators": true
  }
}

类修饰器

ts
// @component编译后就是该函数
function Component(constructor: Function) {
  // 通过运行时函数修改类成员
  constructor.prototype.uniqueId = Date.now();
}

@Component
class ProfileComponent {}

参数修饰器

ts
// 修饰器工厂函数
function Component(value: number) {
  return (constructor: Function) => {
    constructor.prototype.uniqueId = Date.now();
  }
}

@Component(1)
class ProfileComponent{}

修饰器组合

ts
// 多个修饰器将会被组合,顺序调用类似于compose形式:foo(bar())
@Component
@Pipe
class ProfileComponent {}

方法修饰器

descriptor即是当前属性的 描述符 ,通过descriptor用来覆盖原始实现和注入修改逻辑

ts
function Log(target: any, methodName: string, descriptor: PropertyDescriptor) {
  const originalFn = descriptor.value as Function;
  descriptor.value = function(...args: any) {
    console.log('Before');
    originalFn.call(this, ...args);
    console.log('After')
  }
}

class Person {
  @Log
  say(message: string) {}
}

存取修饰器

和属性修饰器不同的是存在于descriptor当中的keys

ts
// method decorator
interface descriptor {
  value
  writable
  enumerable
  configurable
}

// accessor decorator
interface descriptor {
  get
  set
  enumerable
  configurable
}
ts
function Capitalize(target: any, methodName: string, descriptor: PropertyDescriptor) {
  const original = descriptor.get;
  descriptor.get = function() {
    const result = original.call(this);
    return 'newResult';
  }
}

class person {
  @Capitalize
  get fullName() {}
}

属性修饰器

ts
function MinLength(length: number) {
  return (target: any, propertyName: string) => {
    let value: string;
    const descriptor: PropertyDescriptor = {
      set(newVal: string) {
        if (newVal.length < length) throw new Error('xxx');
        value = newVal;
      }
    }
    Object.defineProperty(target, propertyName, descriptor);
  }
}

class User {
  @MinLength(4)
  password: string
}