深入对象

索引签名(Index Signature)

我们已经很熟悉了

1
2
3
4
5
6
7
8
type Hash = {
[key: stirng]: unknown;
length: number;
}
type List {
[key: number]: unknown;
length: number;
}

映射类型(Mapped Type)

多用于泛型

1
2
3
4
5
6
7
type List {
[key in string]: unknown;
}

type List {
[key in number]: unknown;
}

可选类型

对象的某个属性可用可不用

1
2
3
4
5
6
7
8
9
10
interface Person {
name: string;
age: number;
onChange?: () => void;
}

const p: Person = {
name: 'hi',
age: 18
}

只读类型

表示只读,不能写

1
2
3
4
5
6
7
8
9
10
11
12
13
interface Person {
name: string;
age: number;
readonly id: number;
}
const p: Person = {
name: 'hi',
age: 18,
id: 1,
}
p.name = 'new name'

p.id = 2 // TODO: 报错,Cannot assign to 'id' because it is a read-only property.ts

深入函数

对象的语法全都适用于函数,函数也可以用对象来声明

1
2
3
4
5
6
7
type F = {
(a: number, b: number) => void;
count: number;
}

// 普通声明
type F1 = (a: number, b: number) => void

声明方式

JS 函数的三种声明方式

1
2
3
4
5
6
7
8
9
10
11
function f1(a) {
/* ... */
}

const f2 = function(a) {
/* ... */
}

const f3 = () => {
/* ... */
}

那么相对应 TS 的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function f1(a: number): number {
/* ... */
}

const f2 = function (a: number): number {
/* ... */
}

const f3 = (a: number): number => {
/* ... */
}

// 也可以把类型提取出来,写在等号左边,比较推荐
type F2 = (a: number) => number

const f2: F2 = function (a) {
/* ... */
}

可选参数

1
2
3
4
5
function addEventListener(eventType: string, fn: unknown, useCapture?: boolean) { // TODO: 加上问号就好了
/* ... */
}

addEventListener('click', () => 1)

参数默认值

实际情况我们会更倾向于使用默认值

1
2
3
4
5
6
7
// 和上面的代码等价

function addEventListener(eventType: string, fn: unknown, useCapture=false) {
/* ... */
}

addEventListener('click', () => 1)

返回值也是函数

1
2
3
type Add = (x: number) => (y: number) => number

const add: Add = a => b => a + b