TypeScript笔记
# typescript笔记
# 基础
# 什么是typescript
typescript是javascript的超集
# 安装
- 安装命令
npm install -g typescript
1
- 编译
tsc hello.ts
1
# 基本数据类型
布尔值、数值、字符串、null、undefined、Symbol、Object
布尔值
let b: boolean = false
1数值:
let hex: number = 0xf00d // 十六进制 let binary: number = 0b1010 // 二进制 let octal: number = 0o744 // 八进制
1
2
3字符串
let str: string = 'Tom'
1null
let n: null = null
1undefined
let u: undefined = undefined
1
# 任意值
typecript有严格的类型判断,如果everything is any, 就和js差不多
使用任意值
// 以下编译不会出错 let anything: any = 'Tom' any = 7 // 如果变量在声明的时候没有指定其类型,将会被自动识别为任意值 let something
1
2
3
4
5如果在定义变量的时候没有声明类型和赋值,则这个变量自动推论为any类型
let anything anything = 1 anything = 'Tom'
1
2
3
# 联合类型
联合类型表示取值可以有多种类型
let foo: string | number
1注意:访问联合类型的属性和方法的时候,只能访问这些类型的共有属性和方法
# 进阶
# 函数
# 基础
定义方法:函数声明法、匿名函数法
// 函数声明法 function run ():string { return 'run' } // 匿名函数法 var run2 = function ():string { return 'run' }
1
2
3
4
5
6
7
8传参
function getInfo (name:string, age: number):string { // 打印:小明---13 return `${name}---${number}` } // 调用 getInfo('小明', 13)
1
2
3
4
5
6没有返回值
function run ():void {}
1可选参数
function getInfo (name:string, age?: number):string { // 打印:小明---undefined return `${name}---${number}` } // 调用 getInfo('小明')
1
2
3
4
5
6默认参数
function getInfo (name:string, age: number = 20):string { // 打印:小明---20 return `${name}---${number}` } // 调用 getInfo('小明')
1
2
3
4
5
6剩余参数
// 写法一 function sum (...result:number[]):number { // 打印:4 return result.reduce((pre, cur) => pre + cur, 0) } // 调用 sum(1, 1, 1, 1) // 写法二 function sum (a: number, ...result:number[]):number { // 打印:4 return result.reduce((pre, cur) => pre + cur, a) } // 调用 sum(1, 1, 1, 1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 函数重载
function getInfo (name: string):string;
function getInfo (age: number):string;
function getInfo (str: any):any {
if (typeof str === 'string') {
return '我叫:' + str
} else {
return '我的年龄是:' + str
}
}
// 调用
getInfo('小明')
getInfo(13)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 类
# 定义
class Person {
name: string;
constructor (name: string) {
this.name = name
}
run ():void {
console.log(this.name)
}
getName ():string {
return this.name
}
setName (name: string):void {
this.name = name
}
}
// 使用
var p = new Person ('小明')
p.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# getter和setter
- getter
class Person {
// es: 这样定义构造器等同于:constructor(name: string) { this._name = _name }
constructor(private _name: string) {}
get name() {
return this._name
}
}
const person = new Person('dell')
// 打印:dell
console.log(person.name)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- setter
class Person {
// es: 这样定义构造器等同于:constructor(name: string) { this._name = _name }
constructor(private _name: string) {}
get name() {
return this._name
}
set name(name: string) {
this._name = name
}
}
const person = new Person('dell')
// 打印:dell
console.log(person.name)
person.name = 'hello dell'
// 打印:hello dell
console.log(person.name)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 继承
class Person {
name: string;
constructor (name: string) {
this.name = name
}
run ():void {
console.log(this.name)
}
}
class Web extends Person {
constructor (name: string) {
// 初始化父类构造函数
super(name)
}
work () {
console.log(`${this.name}在工作`)
}
}
var w = new Web('小明')
// 打印:小明
w.run()
// 打印:小明在工作
w.work()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 类里的修饰符
三种修饰符
- public :类里面、子类、类外面都可以访问
- protected:类里面、子类可以访问
- private:在类里面可以访
注:属性不加修饰符,默认是public
示例:
// public class Person { public name: string; constructor (name: string) { this.name = name } run ():void { console.log(this.name) } } class Web extends Person { constructor (name: string) { // 初始化父类构造函数 super(name) } work () { console.log(`${this.name}在工作`) } } var w = new Web('小明') var p = new Web('大明') // 打印:大明 console.log(p.name) // 打印:小明 w.run() // 打印:小明在工作 w.work()
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
# 静态属性和静态方法
class Person {
// 实例属性
public name: string;
// 静态属性
static sex = '男'
constructor (name: string) {
this.name = name
}
// 实例方法
run ():void {
console.log(this.name)
}
// 静态方法
static print ():void {
console.log(Person.sex)
}
}
// 调用实例方法,打印:小明
var p = new Person('小明')
p.run()
// 调用实例方法,打印:男
Person.print()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 多态
定义:父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同的表现
示例:
class Animal { name: string; constructor (name: stirng) { this.name = name } // 具体吃什么不知道,需要继承它的子类去实现 eat () { console.log('吃') } } class Dog extends Animal { constructor (name: string) { super(name) } // 实现吃的方法 eat () { return this.name + '吃狗粮' } } class Cat { constructor (name: string) { super(name) } // 实现吃的方法 eat () { return this.name + '吃猫粮' } }
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
# 抽象类
定义:它是提供其他类继承的基类,不能直接被实例化,抽象类中的抽象方法不包含具体的实现并且必须在派生类中实现
示例:
abstract class Animal { public name:string; constructor(name: string) { this.name = name } abstract eat (): any; } // 错误写法,抽象类不能被实例化 // var a = new Animal() class Dog extends Animal { constructor(name: string) { super(name) } // 必须实现抽象类的抽象方法,不实现会报错 eat () { console.log(this.name + '吃狗粮') } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 使用ts实现单例设计模式
class Person {
private static instance: Person;
static getInstance() {
if (!this.instance) {
this.instance = new Person();
}
return this.instance;
}
}
const p1 = Person.getInstance();
const p2 = Person.getInstance();
console.log(p1 === p2)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 接口
概念:接口是对行为的抽象,具体的行动需要由类去实现
示例:
// 1. --------对传入的json参数进行约束------------- function getUserInfo(userInfo: { name: string, age: number }): void { console.log(userInfo) } // 使用 getUserInfo({ name: '小明', age: 12 }) // 2. ---------对传入的对象进行约束---------------- interface UserInfo { name: string; // 注意:分号结束 age: number; } function getUserInfo (userInfo: UserInfo) { console.log(userInfo) } // 使用 var obj = { name: '小明', age: 12 } getUserInfo(obj) // 3. -----------------函数类型接口------------- interface encrypt { (key: string, value: string): string; } var md5: encrypt = function (key: string, value: string): string { return 'md5' + key + value } var sha1: encrypt = function (key: string, value: string): string { return 'sha1' + key + value } console.log(md5('name', '小明')) console.log(sha1('name', '小明')) // 4.----------可索引接口:对数组的约束------------- interface UserArr { [index: number]: string; } var arr: UserArr = ['aaa', 'bbb'] // 5.----------可索引接口:对对象的约束------------- interface UserObj { [index: string]: any; } var obj: UserObj = {name: '张三', age: 12} // 6.----------可索引接口:对类的约束(跟抽象方法很类似)------------- interface Animal { name: string; eat (str: string): void; } class Dog implements Animal { name: string; constructor (name: string) { this.name = name } eat () { console.log(this.name + '吃狗粮') } } // 7. ----------接口的扩展:接口可以继承接口--------- interface Animal { eat(): void; } interface Person extends Animal { work(): void; } class Men implements Person { public name: string; constructor (name: string) { this.name = name } eat () { console.log(this.name + '吃馒头') } work () { console.log(this.name + '写代码') } }
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 泛型
定义:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
示例:
- 要求函数传入string或number,返回string或number
// 1. 使用any(缺点,没有类型校验,传入参数类型和返回值类型不能保持一致) function foo (arg: any): any { return arg } foo('小明') // 2. 使用泛型解决该问题 function foo <T> (arg: T): T { return arg } function bar <T> (arg: T): any { return arg } foo<string>('小明') bar<number>(12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15- 泛型类:比如有个最小堆算法,需要同时支持返回number和string两种类型
class MinClass<T> { public list: T[] = []; add (value: T): void { this.list.push(vlaue) } min (): T { var minNum = this.list[0] for (var i = 0; i < list.length; i++) { if (minNum > this.list[i]) { minNum = this.list[i] } } return minNum } } // 实例化类,并指定了T是number var m1 = new MinClass<number>() m1.add(1) m1.add(33) m1.add(22) console.log(m1.min())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21- 泛型接口
// 1. 定义方法一: interface Config { <T>(key: T, value: T): T } var config: Config = function <T> (key: T, value: T): T { return key + value } // 调用 config<string>('name', '张三') // 2. 定义方法二: interface Config<T> { (key: T, value: T): T } function fun<T> (key: T, value: T): T { return key + value } var config: Config<string> = fun // 调用 config('name', '小明')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 模块
- export、import
# 命名空间
namespace A {
interface Animal {
name: string;
eat(): void;
}
export class Dog implements Animal {
name: string;
constructor (name: string) {
this.name = name
}
eat () {
console.log(`${this.name}在吃狗粮`)
}
}
export class Cat implements Animal {
name: string;
constructor (name: string) {
this.name = name
}
eat () {
console.log(`${this.name}在吃猫粮`)
}
}
}
var d = new A.Dog('柯基')
d.eat()
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
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
# 装饰器
- 定义:装饰器是一种特殊类型的声明,他能够被附加到类声明、方法、属性,可以修改类的行为,通俗来讲,装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
- 常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器
- 装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)
# 类装饰器
- 普通装饰器(不可传参)
// 装饰器
function logClass(params: any) {
// params就是当前类
console.log(params)
params.prototype.apiUrl = '动态扩展的属性'
params.prototype.run = function () {
console.log('run...')
}
}
@logClass
class HttpClient {
constructor () {
}
getData () {
}
}
/* 打印:
http实例类
*/
var http = new HttpClient()
/* 打印:
动态扩展的属性
*/
console.log(http.apiUrl)
/* 打印:
run...
*/
http.run()
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
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
- 装饰器工厂(可传参)
function logClass(params: string) {
// 返回一个函数
return function (target: any) {
// target是当前类、params是传入的参数
console.log(target)
console.log(params)
target.prototype.apiUrl = params
}
}
@logClass('http://127.0.0.1:8080')
class HttpClient {
constructor () {}
getData () {}
}
/* 打印:
http实例类
http://127.0.0.1:8080
*/
var http: any = new HttpClient()
/* 打印:
http://127.0.0.1:8080
*/
console.log(http.apiUr)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- 构造函数重载
function logClass (target: any) {
// 返回一个类
return class extends target {
apiUrl: any = '我是修改后的url'
getData () {
console.log(this.apiUrl)
}
}
}
@logClass
class HttpClient {
public apiUrl: string;
constructor () {
this.apiUrl = '我是url'
}
getData () {
console.log(this.apiUrl)
}
}
var http: any = new HttpClient()
/* 打印:
我是修改后的url
*/
console.log(http.apiUr)
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
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
# 属性装饰器
function logProperty (params: any) {
// 返回一个函数
return function (target: any, attr: any) {
// target是当前类、attr是当前属性名、params是传入的参数
console.log(target)
console.log(attr)
target[attr] = params
}
}
class HttpClient {
@logProperty('http://www.liang2uv.top')
public url: string;
constructor () {
}
getData () {
console.log(this.url)
}
}
/* 打印:
http实例类
url
*/
var http: any = new HttpClient()
/* 打印:
http://liang2uv.top
*/
console.log(http.url)
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
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
# 方法装饰器
function logMethod (params: any) {
// 返回一个函数
return function (target: any, methodName: anym desc: any) {
// target是当前类、methodName是当前方法名称、desc是成员的属性描述符,params是传入的参数
console.log(target)
console.log(methodName)
console.log(desc.value)
// 修改当前类的属性和方法
target.apiUrl = 'xxxx'
target.run = function () {
console.log('run...')
}
// 修改当前方法
var oMethod = desc.value
desc.value = function (...args: any[]) {
args = args.map(value => String(value))
oMethod.apply(this, args)
}
}
}
class HttpClient {
public url: string;
constructor () {
}
@get('http://www.liang2uv.top')
getData (...args: any[]) {
console.log(args)
console.log('我是getData方法')
}
}
/* 打印:
http实例类
getData
getData () {
console.log(this.url)
}
*/
var http: any = new HttpClient()
/* 打印:
xxxx
*/
console.log(http.apiUrl)
/* 打印:
run...
*/
http.run()
/* 打印:
['123', 'xxxx']
我是getData方法
*/
http.getData(123, 'xxxx')
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
上次更新: 2021/11/09, 14:11:00