交叉类型
多个类型合并为一个类型,包含所需的 所有类型 的特性
1 | // T & U 交叉类型 |
联合类型
联合类型表示一个值可以是几种类型之一
1 | const getLength = (content: string | number): number => { |
类型保护
1 | const valueList = ['123', 100] |
类型断言解决
1
console.log((item as string).length || (item as number).toFixed() );
类型保护
1
2
3
4
5
6
7
8function isString (value: string | number): value is string {
return typeof value === 'string'
}
if (isString(item)) {
console.log(item.length);
} else {
console.log(item.toFixed());
}typeof 类型保护
1
2
3
4
5if (typeof item === 'string') {
console.log(item.length);
} else {
console.log(item.toFixed());
}
注意:
- typeof 必须确保
===
或是!===
1
2
3
4
5
6
7
8console.log((typeof item).includes('string')) // true
// 无效
if ((typeof item).includes('string')) {
console.log(item.length);
} else {
console.log(item.toFixed());
} - 类型只能为 基本类型 中的
string | number | boolean | symbol
null && undefined
null && undefined
是特殊的两种类型
- 类型检查器认为
null && undefined
可以赋值为任何类型 -
tsconfig / strictNullChecks
标记可以解决这个问题 - 之后声明一个变量时不会自动包含
null | undefined
1 | let s = 'foo' |
string | undefined 或 string | null 或 string | undefined | null 或 undefined | null 是几个完全不同的类型
去除 null
类型保护
1
2
3
4
5
6
7
8function f(sn: string | null): string {
if (sn == null) {
return "default";
}
else {
return sn;
}
}类型断言
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function getSplicedStr (num: number | null): string {
function getRes (prefix: string) {
// error num 对象可能为 null
// 对于嵌套函数,编译器无法自动去除 null
// return prefix + num.toFixed().toString()
// 1. 类型断言
// num! 表示不为 null
return prefix + num!.toFixed().toString()
// 2. 可选参数
return prefix + num?.toFixed().toString()
}
// 若为 null,则默认值为 0.1 ,但编译器无法识别,需要主动 类型断言
num = num || .1
return getRes('-prefix-')
}
console.log(getSplicedStr(3.141592653)); // -prefix-3
console.log(getSplicedStr(1)); // -prefix-1
console.log(getSplicedStr(null)); // -prefix-0
类型别名
类型别名会给一个类型起个新名字,可以通过 新名字 引用这个对象
使用泛型
1
2
3type PositionType<T> = { x: T, y: T }
const p1: PositionType<number> = { x: 1, y: -1 }
const p2: PositionType<string> = { x: '1', y: '-1' }使用类型别名在属性中引用自己 (只可在对象属性中,不能直接使用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 使用类型别名在属性中引用自己
type Tree<T> = {
value: T,
left?: Tree<T>,
right?: Tree<T>,
}
// 类似树状结构 嵌套
type Childs<T> = {
current: T,
child?: Childs<T>,
}
const c: Childs<string> = {
current: '1st',
child: {
current: '2nd',
child: {
current: '3rd'
}
}
}不能直接使用
1
type Test = Test // error 类型别名“Test”循环引用自身
为接口使用别名时,不能使用
implements | extends
接口和类型别名有时可以起到同样的作用
1
2
3
4
5
6
7
8
9
10
11
12
13type Alias = {
num: number
}
interface Interface {
num: number
}
let _alias: Alias = {
num: 123
}
let _Interface: Interface = {
num: 321
}
_alias = _Interface // 兼容
- 尽量使用接口
interface
代替 类型别名 - 当定义的类型需要通过
implements
进行拓展,则使用interface
- 如果无法通过接口描述一个类型,并且需要使用 联合类型或元组类型 时,通常使用 类型别名
字面量类型
- 字符串字面量类型
1
2
3
4
5
6
7
8
9type Name = 'Tan' // 此处的 'Tan' 作为一个 字符串字面量使用
// const name: Name = '00' // error 不能将类型“"00"”分配给类型“"Tan"”
type Direction = 'north' | 'east' | 'south' | 'west'
function getDirectionInitials (direction: Direction) {
return direction.slice(0, 1).toUpperCase()
}
console.log(getDirectionInitials('north')); // N - 数字字面量类型
1
2
3
4
5
6
7
8
9
10type Age = 18
interface InfoInterface {
name: string,
age: Age
}
const _info: InfoInterface = {
name: 'tan',
age: 100, // error 不能将类型“100”分配给类型“18”
}
可辨识联合类型
可辨识联合两要素
- 具有普通的单例类型属性
- 一个类型别名包含哪些类型的联合
1 | interface Square { |