抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

TypeScript速推

点击这里了解详情:typescript官网

学习训练场:playground

如何使用

在项目中使用npm install typescript即可安装typescript

typescript是javascript的超集,内置许多类型校验功能

以下简称ts

核心

1. 类型推断

在定义变量时,ts会给根据变量设置的初始值会进行类型推断并约束变量的存储数据的类型

1
2
let str = "abc"
str = 3 // 此时会进行报错提示

2. 类型注解

使用类型注解可以约束变量的类

1
2
3
let num: number
num = 10
num = '10' // 此时会进行报错提示

3. 类型断言

使用 as 关键字可对值进行断言处理,大白话就是 使用 as 关键字明确指定 xxx 一定是 xxx 类型

1
2
3
4
5
6
7
8
9
let numArr = [1, 2, 3]
const result = numArr.find(item => item > 2) as number // find方法返回值要么是已找到的数据,要么是undefined,使用类型断言可明确指定方法返回值的类型
console.log(result * 5)


// 如果不进行类型断言
let numArr = [1, 2, 3]
const result = numArr.find(item => item > 2)
console.log(result * 5) // 报错:'result' is possibly 'undefined'.(result可能是undefined)

4. 基础类型和联合类型

基础数据类型

在TypeScript中基础类型和JavaScript一样一共有5个

  1. string (字符串)
  2. number (数字)
  3. boolean (布尔值)
  4. null (空)
  5. undefined (未定义)

在定义变量时使用:对变量进行类型的约束

1
2
3
4
5
let v1: string = 'abc'
let v2: number = 10
let v3: boolean = true
let nu: null = null
let un: undefined = undefined

联合类型

多个类型联合在一起的类型,对变量、参数、返回值等进行约束

使用 | (竖线)对多个类型进行一个连接形成一个 联合类型

Tips: 在TypeScript默认配置中,strictNullChecks这个选项是默认开启的,strictNullChecks表示严格检查null类型,选项的描述是:在进行类型检查时,要考虑null和undefined。

1
let v4: string | null = null // 可以被分配字符串,也可以被分配为null

也可使用具体值进行类型的限制

1
let v5: 1 | 2 | 3 = 4 // 报错:Type '4' is not assignable to type '3 | 1 | 2'. (4不能赋值给1|2|3类型的值)

5. 数组、元祖、枚举等

数组

约束数组的数据类型,有两种写法,和一种默认推断写法

1
2
3
4
5
6
7
8
// 默认推断写法
let arr = [1, 3, '3', null] // 根据类型推断arr的类型为 (number | string | null)[] 可以存储 数字、字符串、null类型的值的数组
// 类型约束方式1
let arr1: number[] = [1, 2, 3]
arr1.push('abc') // 报错:Argument of type 'string' is not assignable to parameter of type 'number'.(‘string’类型的参数不能赋值给‘number’类型的参数。)
// 类型约束方式2
let arr2: Array<number | string> = [1, 3, '3']
arr2.push(null) // 报错:Argument of type 'null' is not assignable to parameter of type 'string | number'.(“Null”类型的参数不能分配给“string | number”类型的参数。)

元组

TypeScript中还提供了类似于数组的结构 —— 元组

元组中的数据量是固定的,也就是长度是固定的,并且每一个位置的数据类型也是被约束的

1
2
3
4
5
6
7
8
let aaa: [number, string, number] = [1, 'abc', 2]
aaa[0] = 'A' // 报错:Type 'string' is not assignable to type 'number' 类型

// 使用可选类型约束定义,将第三位数据改成可选形式
let aaa2: [number, string, number?] = [1, 'abc']
aaa2[2] = 2

let bbb: [number] = [1, 2] // Type '[number, number]' is not assignable to type '[number]'. Source has 2 element(s) but target allows only 1. (类型“[number, number]”不能赋值给类型“[number]”。源有2个元素,但目标只允许1个。)

枚举

enum 关键字声明枚举,枚举相当于一个常量对象

默认设置
1
2
3
4
5
6
7
8
9
// 默认设置
enum MyEnum { A, B, C } // 默认声明的时候对应的是一个数组的形态,从0开始绑定值
console.log(MyEnum.A) // 0
console.log(MyEnum.B) // 1
console.log(MyEnum.C) // 2
console.log(MyEnum[0]) // "A"
console.log(MyEnum[2]) // "B"
console.log(MyEnum[3]) // "C"

enum枚举编译成js后是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["A"] = 0] = "A";
MyEnum[MyEnum["B"] = 1] = "B";
MyEnum[MyEnum["C"] = 2] = "C";
})(MyEnum || (MyEnum = {})); // 默认声明的时候对应的是一个数组的形态,从0开始绑定值
console.log(MyEnum.A); // 0
console.log(MyEnum.B); // 1
console.log(MyEnum.C); // 2
console.log(MyEnum[0]); // "A"
console.log(MyEnum[2]); // "B"
console.log(MyEnum[3]); // "C"
自定义配置

可自定义键和值,类似于定义对象这样

1
2
3
4
5
6
enum MyEnum2 {
getNumber = 1,
getString = "abc"
}
console.log(MyEnum2.getNumber) // 1
console.log(MyEnum2.getString) // “abc”

翻译成JavaScript

1
2
3
4
5
6
7
var MyEnum2;
(function (MyEnum2) {
MyEnum2[MyEnum2["getNumber"] = 1] = "getNumber";
MyEnum2["getString"] = "abc";
})(MyEnum2 || (MyEnum2 = {}));
console.log(MyEnum2.getNumber); // 1
console.log(MyEnum2.getString); // “abc”

6. 函数

函数的定义,可以约束参数类型,和返回值类型

1
2
3
4
5
6
// 约束参数传值,a默认值为10数字类型,b字符串类型,c可选参数布尔型,rest剩余参数数字类型的数组 ;返回值约束为数字
function MyFn(a = 10, b: string, c?: boolean, ...rest: number[]): number{
return 100
}

const fr = MyFn(20, "abc", false, 123, 456, 789)

7. 接口

interface 关键字定义接口,一般用于约束对象的类型,可定义自己的类型进行使用(似乎仅限于对象类型)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface Person {
name: string,
age: number,
gender: 0 | 1
}

let xiaoming: Person = {
name: "小明",
age: 18,
gender: 1
}

let xiaohong: Person = {
name: "小红",
ago: 20, // 报错:Object literal may only specify known properties, and 'ago' does not exist in type 'Person'.(对象字面值可能只指定已知属性,“ago”在“Person”类型中不存在。)
gender: 0
}

let xiaoxue: Person = {
name: "小雪",
age: 20,
gender: "女" // 报错:Type 'string' is not assignable to type '0 | 1'.(仅支持0|1)
}

8. 类型别名

在很多地方都需要使用同样进行约束的时候可使用 type 关键字进行类型声明,并进行使用

1
2
3
4
5
6
// 自定义类型
type MyUserNameType = string | number

let a: MyUserNameType = 3
let b: MyUserNameType = "小颜"
let c: MyUserNameType = NaN // 但要注意NaN也是数字类型,在代码中要注意使用数字和字符串的这种联合类型带来的问题

9. 范型

相当于一个 类型占位符 ,可以传递类型进行灵活约束,自定义约束,等高端操作

核心目的:让代码可以适应多种数据类型,同时保持类型安全。

其次目的:代码复用

如何使用范型:在调用方法的时候参数前的尖括号里添加范型参数

1
2
3
4
5
6
7
8
function myCreateArray<T>(a: T, b: T): T[]{
return [a,b]
}
// 在调用方法的时候传入类型number
const numberResult = myCreateArray<number>(12,23)
console.log(numberResult) // [12, 23]
const stringResult = myCreateArray<string>("A","B")
console.log(stringResult) // ["A", "B"]

进阶

函数重载

javascript中是不支持函数重载的,但在typescript中支持函数重载,也就是

创建多个名称一样,参数类型和返回值不同的函数,以便达到编写一个函数实现多种功能的目的

(tips:但其实可以使用联合类型进行判断后做不同逻辑处理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function hello(name: string): string
function hello(age: number): string
function hello(): string
function hello(value: string | number | void): string{
if (typeof value === 'string') {
return '你好,我的名字是' + value
} else if (typeof value === 'number') {
return `你好,我的年龄是${value}`
} else {
return '非法格式'
}
}

// 传递不同参数实现不同功能
hello('abc')
hello(20)
hello()

接口继承

对接口进行继承并新增,使用extends关键字进行继承操作,继承之后可对新的接口新增属性

目的就是:对接口的功能的进行拓展和更好的复用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 声明接口
interface Parent {
name: string
age: number
gender: number
}

// 继承接口
interface Student extends Parent {
hobby: string
}

// 使用
const myChild: Student = {
name: "小明",
age: 20,
hobby: "打篮球",
gender: 1
}

类及类的修饰符

类,顾名思义 分类 的意思,在代码里 类 ≈ 对象的模具,创建对象的模板,在类当中有许多需要注意的内容

类的修饰符:

  • public 公有属性 (在类的内部外部都可以访问)
  • private 私有属性 (只能在类的内部访问,不可被继承访问,可通过暴露的公共方法获取内部的私有属性值)
  • protected 受保护的属性 (只可在类的内部访问使用,也可被继承的类里访问,可通过暴露的公共方法获取内部的属性值)
  • static 静态属性 (设置给类本身的属性,不是设置给实例,可叠加其他的修饰符对属性进行修饰)
  • readonly 只读属性 (设置属性为只读,不可修改)
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
28
29
30
31
32
33
34
35
36
37
38
39
40
class Article {
// 设置类中必要的属性
public title: string // public修饰符
content: string = "" // 默认不写就是public修饰符
// 设置类中的可选属性
aaa? = 100 // 可设置属性默认值,且自动识别其类型
// 设置类中的私有属性,仅供类内部使用
private bbb = 20

// 设置受保护的可选属性,仅在此类和被继承的类中使用
protected innerData? : string

// 静态、只读的属性
static readonly author: string = '小明'

constructor (title: string, content: string){
// 给必要属性设置属性值
this.title = title
this.content = content
this.innerData = new Date() + ''
// 可在类中使用并修改
this.bbb = 1
Article.author = "小颜" // 报错:Cannot assign to 'author' because it is a read-only property. (不能赋值给‘author’,因为它是一个只读属性。)
}
}

console.log(Article.author) // 类的静态属性可通过类进行访问

const aObj = new Article('标题', '内容')

aObj.aaa
aObj.bbb // 报错:Property 'bbb' is private and only accessible within class 'Article'(属性‘bbb’是私有的,只能在类‘Article’中访问)


class B extends Article {
constructor(title: string, content: string){
super(title, content)
this.innerData // 可对受保护的属性进行继承并访问访问
}
}

便捷写法

1
2
3
4
5
6
7
8
9
10
class Article {
public innerData: string
// 可直接在构造函数的参数里边直接写上修饰符,对传入的参数作为类的属性或者实例属性进行处理
constructor (public title: string, public content: string, private author: string){
// 给必要属性设置属性值
this.title = title
this.content = content
this.innerData = new Date().toString()
}
}

存储器

存储密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class User {
private _password = ""

get password(): string {
return '******'
}

set password(newPass: string) {
this._password = newPass
}

geRealPassword(){
return this
}
}

const u = new User()
console.log('u.password',u.password)
u.password = "my_new_password"
console.log('u.password',u.password)

评论