【内容梳理】ts常用tips

90 阅读2分钟

1. interface使用技巧

1.1 可选属性

interface IPersonAttr {
  id: string;
  name: string;
  favourite?: string | string[];
}

要实现IPersonAttr这个接口的对象:

  • 要有类型为stringid属性和类型为stringname属性
  • favourite属性若有,则为string或者string[]类型
  • favourite属性若无,则为undefined

1.2 继承

interface IStudentAttr extends IPersonAttr {
  level: number;
}

要实现IStudentAttr这个接口的对象:

  • 要有类型为stringid属性和类型为stringname属性
  • 要有类型为numberlevel属性
  • 可以继承多个,以逗号隔开

interface IStudentAttr extends IPersonAttr {
  id: number; // Type 'number' is not assignable to type 'string'
  level: number;
}
  • 继承时,无法实现覆盖,会报错
  • 可以尝试使用Omit<T,K>,这样生成的IStudentAttrid就是number类型了
interface IStudentAttr extends Omit<IPersonAttr, 'id'> {
  id: number;
  level: number;
}

1.3 泛型

interface IAccountAttr<T = any> {
  user: T;
  account: number;
}

const lawsonAccount: IAccountAttr<IStudentAttr> = {
  user: {
    id: 123,
    name: 'lawson',
    level: 3,
  },
  account: 100,
};
  • 实例化时,传递啥类型,内部类型就是啥类型

1.4 可扩展

interface IAccountAttr<T = any> {
  user: T;
  account: number;
  [prop: string]: any; // 扩展属性
}

const lawsonAccount: IAccountAttr<IStudentAttr> = {
  user: {
    id: 123,
    name: 'lawson',
    level: 3,
  },
  account: 100,
  age: 18,
};
  • 可以让IAccountAttr接收额外的属性
  • 不便于检查额外属性类型

2 type

2.1 可选属性

type IPersonAttr = {
  id: string;
  name: string;
  favourite?: string[];
}

2.2 继承

type IStudentAttr = Omit<IPersonAttr, 'id'> & { id: number; level: number };

2.3 罗列

type IDivision = 'liberal arts' | 'science' | 'engineering';
type IPersonAttrKey = keyof IPersonAttr; // 等价于type IPersonAttrKey ='id' | 'name' | 'favourite' 
  • keyof可以获取一个对象、接口的所有key,并罗列

2.3 范围

type IDivisionStudentAttr = {
  [prop in IDivision]: IStudentAttr;
};
  • 对象要实现所有的IDivision接口属性作为key值的可能性

3. enum使用技巧

3.1 对类型的约束

// 表单项的组件类型,即要有formSettings下的name
export enum FormItemTypeEnum {
  INPUT = 'input', // 文本输入框
  INPUTNUMBER = 'inputNumber', // 数值输入框
  ...
}
  • 快速明晰支持哪些类型
  • 快速明晰功能划分思路

3.2 是否产生实体对象

export const enum SplitStyleEnum {
  style11 = 'style11',
  style12 = 'style12',
  style21 = 'style21',
  style22 = 'style22',
  antdStyle1 = 'antdStyle1',
  style3 = 'style3',
}
  • 使用const enum修饰的枚举,build后,不会生成实体,即编译后代码是对应的值
  • const enum一般作为包内部使用,不对外暴露,可以降低代码大小
  • 使用enum修饰的枚举,build后,会生成实体,类似Object,即编译后代码是类源码
  • enum一般需要对外暴露,外部也可以使用此枚举,方便统一

3.3 快速获取所有枚举的列表

Object.values(FormItemTypeEnum)
  • 能拿到上述枚举的所有字符串组成的列表

4. map使用技巧

4.1 当需要枚举的是一个对象时采用

// 表单编辑器type对应的映射对象
export const FormItemMap: IFormItemMap = {
  [FormItemTypeEnum.INPUT]: {
    modelType: ModelItemTypeEnum.TEXT,
    title: '单行文本输入框',
    defaultData: defaultData.inputData,
  },
  [FormItemTypeEnum.INPUTNUMBER]: {
    modelType: ModelItemTypeEnum.DECIMAL,
    title: '数值输入框',
    defaultData: defaultData.inputNumberData,
  },
  ...
};

4.2 简化遍历逻辑

formItems.map((curFormItem) => {
  // 若组件类型名称异常,使用默认的名称
  if (!curFormItem.title) {
    curFormItem.title = FormItemMap[curFormItem.type]?.title;
  }
  const curDefaultData = FormItemMap[curFormItem.type]?.defaultData;
  if (curDefaultData) {
     return mergeData(curFormItem, curDefaultData);
  }
  return curFormItem;
});