学习参考:
高级类型
联合类型 |
-
定义
多个基本类型组成联合类型时,类型可以是若干类型中之一:
type T = boolean | string | number | { id: number };多个自定义类型组成联合类型时,类型为这些自定义类型中属性成员的交集:
type A = { version: string; a: number; } type B = { version: string; b: string; } type T = A | B; // T = { version: string } -
常见作用
函数接收的参数类型可以约束在几种类型当中,这样就解决了函数传入参数类型混乱,或者需要重复定义函数应对不同参数类型的麻烦:
function printValue(value: number | string): void { if (typeof value === 'number') { console.log(`The number is: ${value}`); } else if (typeof value === 'string') { console.log(`The string is: ${value}`); } else { console.log('Invalid input!'); } } printValue(42); // The number is: 42 printValue('Hello'); // The string is: Hello printValue(true); // Invalid input!
交叉类型 &
-
定义
两个类型中成员属性、函数签名、索引签名等的并集:
在类型的属性上,交叉类型是两个或多个类型的并集;但在类型的概念上,交叉类型是两个或多个类型的交集,即既是类型A,又是类型B。
interface Teenager{ name: string; age: number; } interface Student{ grade: number; id: string; } type Undergraduate = Person & Focusable;注意点:成员类型不能是多个原始类型:
type T = string | number | boolean; // type T = never -
常见作用
-
可以通过将多个接口“合并”获得新的类型,便于在原有的接口结构上进行新定义:
interface UserInfo { name: string; age: number; } interface PurchaseHistory { purchasedItems: string[]; totalSpent: number; } // 使用交叉类型创建一个用户对象 type User = UserInfo & PurchaseHistory; const user: User = { name: 'John', age: 30, purchasedItems: ['Shoes', 'Shirt', 'Hat'], totalSpent: 150 }; -
还可以在“合并”的基础上新增接口中的属性:
// 新增需求形成新的类型vip type Vip = User & { id: string, level: number }; const vip: VIP = { name: 'Ali', age: 22, purchasedItems: ['Shoes', 'Shirt'], totalSpent: 300, id: '001', level: 8 }
-
常用操作符
通常在对类型的属性等进行操作时,这几个操作符会一起使用。
-
typeof获取类型,作为一种类型返回:
interface Person{ name: string; age: number; } const ali: Person = { name: 'Ali', age: 21 }; type Alis = typeof ali; // type Alis = Person; -
keyof获取所有键,作为联合类型返回:
interface Person{ name: string; age: number; } type key = keyof Person; // "name" | "age" -
in迭代对象中的元素,和js中的
for...in使用方法相似:type Keys = "a" | "b" | "c"; type Obj = { [k in Keys]: any; } //Obj = { a: any, b: any, c: any } -
T[k]索引类型,类似于数组中按照索引取元素:
interface Person { name: string; age: number; } let name: Person['name'] // let name: string
声明文件
使用declare关键字进行变量类型声明的.d.ts文件被称为声明文件:
// sample.d.ts
declare module 'some-library' {
export function doSomething(arg: string): number;
export const value: string;
}
这些文件不包含具体的实现代码,而是仅包含类型声明。通常用于在TypeScript项目中提供类型检查和代码补全的支持,使得在使用第三方JS库、模块或一些没有提供TS支持的库时,不会出现“缺少类型”的提示。通常声明文件存放在项目的根目录下。
一般第三方js插件在npm上都有对应的声明文件,可以通过@types/xxx关键字进行引入:
npm i @types/jquery
泛型
工具类型
-
Partial<T>让类型中的属性可选:
type Partial<T> = { [P in keyof T]?: T[P]; } -
Required<T>让类型中的属性必选:
其中
-?表示属性必选。type Required<T> = { [P in keyof T]-?: T[P]; } -
Readonly<T>让类型中的属性只可读:
type Raedonly<T> = { readonly [P in keyof T]: T[P] }
使用举例
可以用于限制向后端接口发起请求的参数规范。如定义一个接口传参规范:
import axios from 'axios';
interface API {
'/book/detail': {
id: number,
},
'/book/comment': {
id: number,
comment: string
}
}
// 接口与其参数的结构相对应
function request<T extends keyof API>(url: T, obj: API[T]){
return axios.post(url, obj)
}
那么发起请求的接口和传入的参数结构不对应时就会出现报错:
// 路径错误
request('/book/test', {
id: 123,
comment: 'hello'
})
// 参数错误
request('/book/detail', {
id: 123,
comment: 'hello'
})