编程崽

登录

一叶在编程苦海沉沦的扁舟之上,我是那只激情自射的崽

TS常用技巧

TS常用技巧

一些常用的Ts体操的记录,部分功能的实现会使用 TS 自动的一些实用程序类型。

为window添加字段

ts 复制代码
// 给Window添加字段
declare interface Window {
  flag: string, // 给Window添加这个字段
  apple: string | number, // 给Window添加这个字段
}

为无声明文件的第三方包添加声明

ts 复制代码
// 可以给qs这个无类型的第三方包声明类型,声明成了any
declare module 'qs';
// 或者
declare type qs = {
  // ...
}

字符串数组生成type

把下面这个字符串数组,每一项的数组,转为 type 罗列出来:

ts 复制代码
const arr = ['apple', 'car', 'tree']
// 目标,根据上面的现有的数组,得到下面的类型
type Arr = 'apple' | 'car' | 'tree'

进行转换的方法:

ts 复制代码
// 先把数组进行 as const 转为不可修改的常量
const arr = ['apple', 'car', 'tree'] as const
// 使用方法生成类型
type Arr = typeof arr[number]
// 最终 type Arr = 'apple' | 'car' | 'tree'

把对象的key生成type

ts 复制代码
let obj = {
  apple: 1,
  car: 2,
  tree: 3,
}

// 目标,根据上面的现有的对象,得到下面的类型
type ObjKey = 'apple' | 'car' | 'tree'

进行转换的方法:

ts 复制代码
// 直接使用方法生成类型
type ObjKey = keyof typeof obj; 
// 最终 type ObjKey = 'apple' | 'car' | 'tree'

对象数组中某字段的值组成type

比如,我有对象数组,我想把对象数组中每个对象的 value 字段的值取出来,得到一个 type

ts 复制代码
// 对象数组
const options = [
  {
    label: '输入框',
    value: 'input',
  },
  {
    label: '下拉框',
    value: 'select',
  },
]

// 想得到
// type OptionValue = 'input' | 'select'

// 那么这么写
type OptionValue = typeof options[number]['value']
// 最终等效于
type OptionValue = 'input' | 'select'

提取类型中的某几个字段得到新类型

使用 ts 的 Pick 这个实用程序类型。

ts 复制代码
// 声明类型
type Tab = { a: string, b: number, c: string };

// 只保留 a 和 b 这两个字段
type TabChild = Pick<Tab, 'a' | 'b'>;
// 最终的 TabChild = { a: string, b: number };

排除类型中的某几个字段得到新类型

使用 ts 的 Omit 这个实用程序类型。

ts 复制代码
// 声明类型
type Tab = { a: string, b: number, c: string };

// 排除 a 和 b 这两个字段
type TabChild = Omit<Tab, 'a' | 'b'>;
// 最终的 TabChild = { c: string };

把类型中所有字段都设为可选,得到新类型

使用 ts 的 Partial 这个实用程序类型。

ts 复制代码
// 声明类型
type Tab = { a: string, b: number, c: string };

// 设为可选
type TabChild = Partial<Tab>;
// 最终的 TabChild = { a?: string, b?: number, c?: string };

把类型中所有字段都设为必选,得到新类型

使用 ts 的 Required 这个实用程序类型。

ts 复制代码
// 声明类型
type Tab = { a?: string, b?: number, c?: string };

// 设为必选
type TabChild = Required<Tab>;
// 最终的 TabChild = { a: string, b: number, c: string };

把类型中所有字段都设为只读,得到新类型

使用 ts 的 Readonly 这个实用程序类型。

ts 复制代码
// 声明类型
type Tab = { a: string, b: number, c: string };

// 设为只读
type TabChild = Readonly<Tab>;
// 最终的 TabChild = { readonly a: string, readonly b: number, readonly c: string };

传入一个Promise,得到这个Promise返回值的类型

ts没有提供对应实用程序类型,需要自己写。

注意下面是传入一个Promise,不是Promise方法

ts 复制代码
// 定义,传入一个Promise,返回一个Promise返回值的类型
type ExtractPromiseType<T> = T extends Promise<infer U> ? U : never;

// 手写一个Promise
let somePromise = new Promise<string>((resolve) => {
	setTimeout(() => {
		resolve('1212')
	}, 3000);
})

// 得到Promise的类型
type SomePromiseResult = ExtractPromiseType<typeof somePromise>;
// 最终 SomePromiseResult = string

传入异步的Promise函数,得到这个异步方法返回值的类型

ts没有提供对应使用程序类型,需要自己写,也会需要用到上面自行封装的实用程序。

ts 复制代码
// 定义,传入一个Promise,返回一个Promise返回值的类型
type ExtractPromiseType<T> = T extends Promise<infer U> ? U : never;

// 定义,传入一个Promise异步方法,返回这个Promise异步方法的返回值类型
type AsyncReturnType<T extends (...args: any) => Promise<any>> = ExtractPromiseType<ReturnType<T>>;

// 手写一个异步Promise方法
async function getNum() {
	return 1234
}

// 得到这个异步Promise方法的返回值类型
type GetNumResult = AsyncReturnType<typeof getNum>
// 最终 SomePromiseResult = number

传入非异步的普通方法,得到这个方法返回值的类型

使用 ts 的 ReturnType 这个实用程序类型。

ReturnType是传入一个方法类型的Type,最终得到这个方法返回的值的类型。

ts 复制代码
function getStr(num: number) {
  if (num > 1) return num
  else return '小于1'
}

type GetStrReturnType = ReturnType<typeof getStr>
// type GetStrReturnType = number | "小于1"

type T0 = ReturnType<(s: string)=> void>
// type To = void

type T1= ReturnType<any>
// type T1 = any

type T2 = ReturnType<never>
// type T1 = never