ts base

unknown

1
2
3
4
5
6
7
8
我们可以通过不同的方式将 unknown 类型缩小为更具体的类型范围
function getLen(value: unknown): number {
if (typeof value === 'string') {
// 因为类型保护的原因,此处 value 被判断为 string 类型
return value.length
}
return 0
}

联合类型 “或”

1
2
3
4
5
6
7
function foo(x: string | any[]) {
return x.length
}

foo('') // ok
foo([]) // ok
foo(1) // error

交叉类型 “与”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface Person {
name: string
age: number
}

interface Animal {
name: string
color: string
}

const x: Person & Animal = {
name: 'x',
age: 1,
color: 'red
}

typeof 关键词

1
2
3
4
5
6
7
function fn (x: string | number) {
if (typeof x === 'string') { // x is string
return x.length
} else { // x is number
// .....
}
}

in

1
2
3
4
// in 可以对联合类型进行遍历,只可以用在 type 关键词下面
type Person = {
[key in 'name' | 'age']: number
}

keyof

1
2
3
4
5
6
7
// 可以用来取得一个对象接口的所有 key 值
interface Person {
name: string
age: number
}

type PersonAttrs = keyof Person // 'name' | 'age'

in 和 keyof组合

1
2
3
4
5
6
7
8
9
10
type Copy<T> = {
[key in keyof T]: T[key]
}

interface Person {
name: string
age: number
}

type Person1 = Copy<Person>

泛型

相当于一个类型的参数,在 ts 中,泛型可以用在 类、接口、方法、类型别名 等

1
2
3
4
5
6
function createList<T>(): T[] {
return [] as T[]
}

const numberList = createList<number>() // number[]
const stringList = createList<string>() // string[]

映射类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Partial<T> -- 将 T 中的所有属性变成可选。
Readonly<T> -- 将 T 中的所有属性变成只读。
Pick<T, U> -- 选择 T 中可以赋值给U的类型。
Exclude<T, U> -- 从T中剔除可以赋值给U的类型。
Extract<T, U> -- 提取T中可以赋值给U的类型。
NonNullable<T> -- 从T中剔除null和undefined。
ReturnType<T> -- 获取函数返回值类型。
InstanceType<T> -- 获取构造函数类型的实例类型。

写 TS 时可以直接使用这些类型工具
interface ApiRes {
code: string;
flag: string;
message: string;
data: object;
success: boolean;
error: boolean;
}

type IApiRes = Pick<ApiRes, 'code' | 'flag' | 'message' | 'data'>

// {
// code: string;
// flag: string;
// message: string;
// data: object;
// }

全局模块 vs 文件模块

  • 默认情况下,我们所写的代码是位于全局模块下的:const foo = 2

复制代码此时,如果我们创建了另一个文件,并写下如下代码,ts 认为是正常的:
const bar = foo // ok
复制代码如果要打破这种限制,只要文件中有 import 或者 export 表达式即可:
export const bar = foo // error

模块解析策略

ts两种模块的解析策略:Node 和 Classic

  • tsconfig.json 中 module 设置成 AMD、System、ES2015 时,默认为 classic

  • 否则为 Node ,也可以使用 moduleResolution 手动指定模块解析策略

1
2
3
4
5
6
7
8
9
10
11
12
import module from 'module'

// Classic 路径寻址:

/root/src/folder/module.ts
/root/src/folder/module.d.ts
/root/src/module.ts
/root/src/module.d.ts
/root/module.ts
/root/module.d.ts
/module.ts
/module.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Node 路径寻址:

/root/src/node_modules/module.ts
/root/src/node_modules/module.tsx
/root/src/node_modules/module.d.ts
/root/src/node_modules/module/package.json (如果指定了"types"属性)
/root/src/node_modules/module/index.ts
/root/src/node_modules/module/index.tsx
/root/src/node_modules/module/index.d.ts
|
v
/root/node_modules/module.ts
/root/node_modules/module.tsx
/root/node_modules/module.d.ts
/root/node_modules/module/package.json (如果指定了"types"属性)
/root/node_modules/module/index.ts
/root/node_modules/module/index.tsx
/root/node_modules/module/index.d.ts

声明文件

  • 文件以 .d.ts 结尾,用来描述代码结构,一般用来为 js 库提供类型定义,如果某个包的根目录下有一个index.d.ts,那么这就是这个库的声明文件了

  • 如果这个包的package.json中有types或者typings字段,那个该字段指向的就是这个包的声明文件

  • 如果某个库很长时间不维护了,typescript官方提供了一个声明文件仓库,尝试使用@types前缀来安装某个库的声明文件

扩展原生对象

如何在 window 对象上自定义属性

1
window.myprop = 1 // error

可以输用方括号赋值语句,但是 get 操作时也必须用 [] ,并且没有类型提示

1
window['myprop'] = 1 // OK

可以使用声明文件扩展其他对象,在项目中随便建一个xxx.d.ts

1
2
3
4
5
6
7
// index.d.ts
interface Window {
myprop: number
}

// index.ts
window.myprop = 2 // ok

也可以在模块内部扩展全局对象

1
2
3
4
5
6
7
window.myprop = 2

declare global {
interface Window {
myprop: number
}
}
返回
顶部