TypeScript 学习总结

TypeScript 学习总结

TypeScript 定义

TypeScript 是一个 JavaScript 的超集,主要提供了对类型系统和 ES6 的支持。
目前 JS 引擎无法读取 TS 代码,因此任何 TS 文件都有一个预编译的过程。

TS 作用

TypeScript 是 JS 静态检查的最佳工具。在代码运行之前测试代码的正确性。 TS 会让 JS 的代码结构更好。

到目前为止,JS 有 7 种类型:

1
2
3
4
5
6
7
1. String
2. Number
3. Boolean
4. Null
5. Undefined
6. Object
7. Symbol(es6)

在使用 JS 进行开发的时候,声明变量的类型是可以随时改变的, 例如布尔类型可以变成字符串。js 松散的特性可能会在代码中造成严重的问题,破坏其可维护性。
TS 则可以通过向 JS 添加强类型检测,来避免这些问题。

1
2
let bool = true
bool = 'string'

TS 的常用数据类型

常用的类型:boolean、number、string、null、undefined、Symbol、void 空类型、any等等。
可以去官网查看完整的TS 数据类型

1.Boolean

1
const isDone: boolean = false

2.Number

1
const decimal: number = 1

3.联合类型和 type 类型别名

1
2
3
4
5
6
type possible = string | number
let data: possible = 123

let myNumber: string | number
myNumber = '123'
console.log(myNumber.length)

4.枚举 Enum

用于取值被限定在一定范围的场景内,比如一周只有7天。

1
2
3
4
5
6
7
enum Color = {
Red,
Green,
Blue
}

const c: Color = Color.Red

5.函数类型

5.1可选参数用 ? 表示。可选参数必须在必需参数的后面。

1
2
3
4
5
6
7
function addCount(a: number, b?: number) {
if (b) {
return a + b
} else {
return a
}
}

5.2 默认参数,在 es6 中我们允许给函数的参数添加默认值, TS 会将添加了默认值的参数识别为可选参数,此时不再受到可选参数
必须在必需参数后面的限制了。

1
2
3
4
5
function addCount(a: number = 1, b: number) {
return a + b
}

console.log(addCount(undefined, 2))

泛型

定义:是指在定义函数,接口或者类的时候,不预先制定具体的类型,而在使用的时候在指定类型的一种特性。

通俗的解释,泛型是类型系统中的“参数”,主要作用是为了类型的重用。从定义可以看出,它只会用在函数,接口或者类中。因为 TS 是静态类型系统,是在 JS 进行编译
时进行类型检查的系统,因此,泛型这种参数,实际上在编译过程中的运行时使用。

泛型函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function identity<T>(value: T): T {
return value
}

identity<number>(123) // 123

// 传递2个类型
function identity<T, U>(value: T, message: U): T {
console.log(message)
return value
}

const res = identity<number, string>(123, 'test')
console.log(res) // 信息 123

T 被称为类型变量

T 代表 type, 在定义泛型时通常用作第一个类型变量的名称。但实际上 T 可以用作任何有效名称替代。除了 T 之外,还有其他常见的泛型变量:

1
2
3
K(key): 表示对象中的键类型
V(Value): 表示对象中的值类型
E(Element): 表示元素类型
1
2
3
4
5
6
7
8
9
function createArr(length: number, value: any): Array<any> {
let res = []
for (let i = 0; i < length; i++) {
res.push(value)
}
return res
}

createArr<string>(3, 'x') // ['x', 'x', 'x']

Array 允许数组的每一项都为任意类型。但是我们的预期是数组中每一项都应该是输入的 value 类型。所以 createArr 函数可以改为

1
2
3
4
5
6
7
8
9
10
11
// 在函数名后添加了 <T>, 其中用 T 表示任意输入的类型,在后面输入的 value: T 和输出的 Array<T> 中皆可使用
function createArr<T>(length: number, value: T): Array<T> {
let res: T[] = []
for (let i = 0; i < length; i++) {
res.push(value)
}
return res
}

// 在调用的时候,可以指定具体的类型,也可以不指定,而让类型推论自己推算出来
createArr(3, 'x') // ['x', 'x', 'x']

泛型接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 泛型接口
interface identities<T, U> {
value: T,
msg: U
}

function identity<T, U>(value: T, msg: U) {
let text: identities<T, U> = {
value,
msg
}
return text
}

identity(123, 'test') // { value: 123, msg: 'test' }

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 泛型类
interface InterfaceTest<U> {
value: U,
getIdentity: () => U
}

class IdentityClass<T> implements InterfaceTest<T> {
value: T

constructor(value: T) {
this.value = value
}

getIdentity(): T {
return this.value
}
}

const test = new IdentityClass<number>(123)
console.log(tes.getIdentity()) // 123

什么时候使用泛型?
1.当函数、接口和类将处理多种数据类型时
2.当函数、接口或类在多个地方使用该数据类型时

TypeScript 对象和接口

1.Array 如果访问数组对象中的属性,会报错,因为普通 JS 对象中没有对象的属性。
2.interface 接口 (由类去实现)

TS 的核心原则之一,就是对值的结构进行类型检查,在 TS 中,会使用接口 interfaces 来定义对象的类型。

用接口来定义一个模型,放在代码的顶部。

1
2
3
4
5
6
7
interface ILink {
url: string,
getName(a: number): void
}

// 在定义接口名字前面加上大写的 `I`, 这是 TS 的惯例
Array<ILink>

接口和字段

TS 接口是该语言最强大的结构之一。接口有助于整个应用程序中形成模型,参与项目的开发人员都需要遵循此模型。

TS 中可以通过函数声明来推断参数是 ILink 的类型数组。因此,该数组中的任何对象都必需实现接口 ILink 中定义的所有字段。
但在大多数情况下,实现所有字段不太现实。可以声明接口的字段是可选的,用 ? 表示。

1
2
3
4
5
interface ILink = {
des?: string,
id?: number,
url: string
}

接口继承接口

在 TS 中可以使用继承来扩展接口,关键字 extends 表示;扩展接口意味着其属性并扩展他们以实现代码重用。

1
2
3
4
5
6
7
8
9
10
interface ILink {
...
}


// 接口继承, 在 ILink 的接口上新增 title 和 body 字段
interface IPost extends ILink {
title: string,
body: string
}

类实现接口

实现 implements 是面向对象中的一个重要概念。一般来讲,一个类只能继承自另外一个类,有时候不同的类之间可以有一些共同的特性。可以把特性
提取成接口 interfaces, 用 implements 关键字来实现。

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
interface IAlarm {
alertMethod(): void;
}

interface ILight {
lightOn(): void;
}

class Door {}

class SecurityDoor extends Door implements IAlarm {
alertMethod() {
console.log('alert method')
}
}

class Car implements IAlarm, ILight {
alertMethod() {
console.log('alert method')
}

lightOn() {
console.log('light on')
}
}

接口继承类

声明合并

如果定义来两个相同名字的函数、接口或者类,他们会合并成一个类型。

1
2
3
4
5
6
7
interface IAlarm {
...
}

interface IAlarm {
weight: number
}

class 和 interface 的区别

由于 TS 的宗旨是兼容 JS ,运行时要擦除所有类型信息,因此 interface 在运行时是被完全消除的。而 class 经过编译后,在运行时依然存在。因此要声明的类型只是纯粹的类型信息,只需要声明 interface 即可。