JNUfeatherwit / blog

6 stars 0 forks source link

ts规范 #17

Open JNUfeatherwit opened 2 years ago

JNUfeatherwit commented 2 years ago

基本原则

1、any类型少用或不用

反例:

interface IProps{
   text: any;
   onClick:()=>any
}

正例:

interface IProps{
   text: string;
   onClick:()=>void
}

2、使用泛型,使得类型的确定时机置于使用时

反例:

  function get (
    url: string,
    params?: any,
  ): Promise<any> {
    return this.request({
      method: 'get',
      url: this.getApiUrl(url, params),
    });
  }; // 无法做出入参类型校验

正例:

  function get<P,R> (
    url: string,
    params?: P,
  ): Promise<R> {
    return request({
      method: 'get',
      url: this.getApiUrl(url, params),
    }) as R;
  };
// 使用
get<IParams,IResult>(url,{})

3、函数入参需写类型,有默认值可以不写,可选参数置于右边,出参根据情况可写可不写

export const sleep = (time = 500,arg1:number,arg2?:number) => {
  return new Promise<void>((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
};

4、类型的命名

1、object类型 只可使用interface关键字,命名前缀加“I”代表是interface类型 正例:

interface IObject {
  [key: string]: any;
}
interface IRequestOptions {
  method?: string;
  data?: IObject;
  headers?: IObject;
  url?: string;
  [key: string]: any;
}

注意: 服务端接口的入参类型如果为object类型,需使用服务端的类型/实体类名称来命名,格式为'I'+【类型名称】,防止多个接口使用同一个实体类时前端维护多个不同名称的类型; 如果是入参,命名则是“I”+【接口名称驼峰】+"Params" 正例:

// 入参
interface IUpdateBusinessInfoParams {
  id: string;
  highInsuranceExpires?: number;
  commercialInsuranceExpires?: number;
  nextAnnual?: number;
  nextMaintain?: number;
}
// 出参
interface IStdName {
  categoryCode: string;
  categoryName: string;
  stdName: string;
  stdNameCode: string;
}

如何知道服务端提供的类型名称:

反例:

if(type===1){
  console.log('HOUR')
}

正例:

enum TimeType{
   HOUR=1,
   SECONDS=2,
}
if(type===TimeType.HOUR){
  console.log('HOUR')
}

6、类型较多时或者需要给其他文件用时,需要建立typings.ts文件来专门定义类型文件,防止出现循环引用

(1)全局类型

在src目录下新建typings文件夹,如果是export方式,后缀为.ts;如果是declare方式,后缀为.d.ts

└── typings ├── common.ts ├── big.d.ts

注意一下declare,declare是用来全局声明一个变量、模块、类型、作用域,用来告诉TS编译器你担保这些变量和模块存在,并声明了相应类型,在项目里可直接使用这些全局属性,不需要import

declare module 'foo' {
    export interface Foo {
        foo: string;
    }
}

declare module 'bar' {
    export function bar(): string;
}

/ src/index.ts

import { Foo } from 'foo';
import * as bar from 'bar';

let f: Foo;
bar.bar();

(2) 接口相关类型

接口文件结构(分为接口的定义和类型的定义) └── api ├── store.ts ├── car.ts └── typings ├── store.ts ├── car.ts

export async function getCustomerCarList(
  params: ISearchParams,
){
  return await requestWrapper<ISearchParams, IPaged<ICarInfo>>(
    Http.get,
    '/saas-api/customer/car/list',
    params,
  );
}
export interface ISearchParams {
  keyword?: string;
  pageNum?: number;
  pageSize?: number;
}
export interface ICarInfo {
  id?: string; 
  carType: number; 
  carNo: string;
}

(3) 其他情况 定义typings.ts文件

7、类型的扩展

1、联合类型、交叉类型

A|B // 要求类型满足A或B
A&B //要求类型同时满足A和B

2、类型的泛型

// 分页类型
export interface IPaged<T> {
  list: T[];
  pageNum: number;
  hasNextPage: boolean;
  pageSize: number;
  pages?: number;
  size?: number;
  total: number;
}

3、一些内置的常用的工具泛型

type A = ReturnType; // => number

- Record : 定义对象的key和value

interface PageInfo { title: string; }

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = { about: { title: "about" }, contact: { title: "contact" }, home: { title: "home" }, };

lolicrafter commented 9 months ago

学到了,谢谢大佬