1. is关键字
is关键字可用来判断并限定值的类型,比如:
function user0(name: any): name is string {
return name === 'lili'
}
function user1(name: any): boolean {
return name === 'lili'
}
function getUserName(name: string | number) {
if(user0(name)) {
console.log(name)
console.log(name.length)
/**
* 若换成user1(name) boolean就会报错
* Property 'length' does not exist on type 'string | number'.
* Property 'length' does not exist on type 'number'.
*/
}
}
getUserName('lili')
is关键字和boolean的区别大概就在于is可以限定值的类型,类似于boolean+类型断言的作用
2. 可辨识联合类型
为可辨识的特征创建适合的联合类型
interface Info {
username: string
}
// bad
interface UserAction {
id?: number
action: 'create' | 'delete'
info: Info
}
// good
type UserAction = {
id: number
action: 'delete'
info: Info
} |
{
action: 'create'
info: Info
}
const UserReducer = (userAction: UserAction) => {
switch (userAction.action) {
case 'delete':
console.log(userAction.id);
break;
default:
break;
}
}
3. typeof
通过typeof可以得到某个值的类型,比如:
/** bad */
interface Opt {
timeout: number
}
const defaultOption: Opt = {
timeout: 500
}
/** good */
const defaultOption = {
timeout: 500
}
type Opt = typeof defaultOption
当一个对象具有字面量初始值时,可以考虑这种写法以减少重复代码
4. keyof & condition type
- keyof可获取类型上的键值,比如:
type Person = {
id: number;
name: string;
}
// 等价于type keys = "id" | "name"
type keys = keyof Person;
- 条件类型(condition type)可用于判断类型T是否扩展于U
T extends U ? X : Y
比如:
type Exclude<T, U> = T extends U ? never : T;
// 等价于type T = 'b'
type T = Exclude<'a' | 'b' | 'c', 'a' | 'c'>
当T为联合类型的时候,它会自动分发条件。
5. 常用工具类型
- Partial & Required & Pick
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Required<T> = {
[P in keyof T]-?: T[P];
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface User {
id: number;
age: number;
name: string;
};
// 相当于: type PartialUser = { id?: number; age?: number; name?: string; }
type PartialUser = Partial<User>
// 相当于: type PickUser = { id: number; age: number; }
type PickUser = Pick<User, "id" | "age">
+
-
这两个关键字用于映射类型中给属性添加修饰符,比如-?就代表将可选属性变为必选
- Omit
Omit<T, K>
的作用是忽略T中的K属性.
type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }
// 等价于type Foo = { age: number }
type Foo = Omit<{name: string, age: number}, 'name'>
- Record
Record<K, T>
可将K中所有属性的值转化为T类型.
type Record<K extends string | number | symbol, T> = { [P in K]: T; }
enum AnimalType {
CAT = 'cat',
DOG = 'dog',
FROG = 'frog',
}
interface AnimalDescription {
name: string,
icon: string
}
const AnimalMap: Record<AnimalType, AnimalDescription> = {
cat: { name: '猫', icon: '🐱'},
dog: { name: '狗', icon: '🐶' },
frog: { name: '蛙', icon: '🐸' },
};
- ReturnType
ReturnType
可用来获取函数的返回类型
type ReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R :
any;
function foo(x: number): Array<number> {
return [x];
}
// 等价于type fn = number[]
type fn = ReturnType<typeof foo>;
在条件类型语句中,
infer
关键字可声明一个类型变量并对它进行使用,这里是判断T
如果为( ...args: any[] ) => infer R
函数类型的子类型,则返回R
,否则返回any
.
tsv3.7特性
1. 可选链
通过可选属性访问操作符?.
可选择性的对数据进行访问,通过这种方式,如果存在尚未定义的父级对象(null或undefined)
,则会在链中的任何位置返回undefined
,而不是在运行时崩溃.
// before
if(data && data.customer && data.customer.address){
const {address} = data.customer;
....
}
// now
const address = data?.customer?.address;
// 也适用于数组
customer?.[0]?.['address']
// 检查方法是否已定义并调用
customer.approve?.()
?.
的行为与使用&&实现的代码不同,因为&&专门用于“假值”(空字符串、0、NaN、false)的判断,但?.
却不会在遇到有效数据(如:0和空字符等)的时候短路.
2. 空值合并
如果左侧是null
或undefined
,空值合并运算符??
会返回右侧的表达式.
// before
const x = data || 'defaultValue';
// now
const x = data ?? 'defaultValue';
同样,相比
||
运算符,??可排除有效数据如0、false
等的短路.
3. 断言签名
断言签名可对node.js assert
功能进行模拟,或者不检查条件而告诉ts
特定的变量具有不同的类型.
function assert(condition: any, msg?: string): asserts condition {
if (!condition) {
throw new AssertionError(msg)
}
}
function assertIsString(val: any): asserts val is string {
if (typeof val !== "string") {
throw new AssertionError("Not a string!");
}
}
更多特性可翻阅Roadmap