# TypeScript 进阶
# 类型别名
类型别名用来给一个类型起个新名字
type Name = string
type NameResolver = () => string
type NameOrResolver = Name | NameResolver
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n
} else {
return n()
}
}
别名可以定义泛型
# 字符串字面量类型
字符串字面量类型用来约束取值只能是某几个字符串中的一个
🤔 数字类型可以吗
type EventNames = 'click' | 'scroll' | 'mousemove'
function handleEvent(ele: Element, event: EventNames) {
// do something
}
handleEvent(document.getElementById('hello'), 'scroll') // 没问题
handleEvent(document.getElementById('world'), 'dblclick') // 报错,event 不能为 'dblclick'
// index.ts(7,47): error TS2345: Argument of type '"dblclick"' is not assignable to parameter of type 'EventNames'.
# 元组
数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象
let tom: [string, number] = ['Tom', 25]
# 使用
import { useState } from 'react'
const [loading, setLoading] = useState<boolean>(false)
function useState<S = undefined>(): [
S | undefined,
Dispatch<SetStateAction<S | undefined>>
]
# 枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。
enum Days {
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
}
// 编译后的代码
var Days
;(function(Days) {
Days[(Days['Sun'] = 0)] = 'Sun'
Days[(Days['Mon'] = 1)] = 'Mon'
Days[(Days['Tue'] = 2)] = 'Tue'
Days[(Days['Wed'] = 3)] = 'Wed'
Days[(Days['Thu'] = 4)] = 'Thu'
Days[(Days['Fri'] = 5)] = 'Fri'
Days[(Days['Sat'] = 6)] = 'Sat'
})(Days || (Days = {}))
# 手动赋值
enum Days {
Sun = 7,
Mon = 1,
Tue,
Wed,
Thu,
Fri,
Sat
}
//未手动赋值的枚举项会接着上一个枚举项递增 // 7123456
# 常数枚举
const enum Days {
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
}
常数枚举与普通枚举的区别是,它会在编译阶段被删除
# 外部枚举
外部枚举(Ambient Enums)是使用 declare enum 定义的枚举类型 declare 定义的类型只会用于编译时的检查,编译结果中会被删
🤔 如果定义一个能够循环选项的枚举类型
# 类 (opens new window)
# 类和接口 (opens new window)
# 泛型
- T(Type):表示一个 TypeScript 类型
- K(Key):表示对象中的键类型
- V(Value):表示对象中的值类型
- E(Element):表示元素类型
在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
# 声明合并
如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型:
# 函数的合并 重载
# 接口合并 类的合并 接口中的属性在合并时会简单的合并到一个接 合并的属性的类型必须是唯一的
# 类型守卫
类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。换句话说,类型保护可以保证一个字符串是一个字符串,尽管它的值也可以是一个数值。类型保护与特性检测并不是完全不同,其主要思想是尝试检测属性、方法或原型,以确定如何处理值
# in
# typeof
# instanceof
# 泛型工具类型
- typeof
在 TypeScript 中,typeof 操作符可以用来获取一个变量声明或对象的类型
interface Person {
name: string
age: number
}
const sem: Person = { name: 'Ivan', age: 18 }
type Sem = typeof sem // -> Person
- keyof
keyof 操作符可以用来一个对象中的所有 key 值
interface Person {
name: string
age: number
}
type K1 = keyof Person // "name" | "age"
type K2 = keyof Person[] // "length" | "toString" | "pop" | "push" | "concat" | "join"
type K3 = keyof { [x: string]: Person } // string | number
- in
in 用来遍历枚举类型:
type Keys = 'a' | 'b' | 'c'
type Obj = {
[p in Keys]: any
} // -> { a: any, b: any, c: any }
- infer
在条件类型语句中,可以用 infer 声明一个类型变量并且对它进行使用
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any
以上代码中 infer R 就是声明一个变量来承载传入函数签名的返回值类型,简单说就是用它取到函数返回值的类型方便之后使用。
https://juejin.cn/post/6844904170353328135
- extends
有时候我们定义的泛型不想过于灵活或者说想继承某些类等,可以通过 extends 关键字添加泛型约束。
interface ILengthwise {
length: number
}
function loggingIdentity<T extends ILengthwise>(arg: T): T {
console.log(arg.length)
return arg
}
- Partial
Partial<T>
的作用就是将某个类型里的属性全部变为可选项 ?。
/**
* node_modules/typescript/lib/lib.es5.d.ts
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P]
}