TypeScript

类型

any | unknown

image-20230709200535549

Object object {}

Object: 它是可以赋值为任意类型的变量的
object: 它只能被非原始数据类型所赋值(如数组、对象、方法等)
**{}**: let a: {} = 123 等价与new Object,跟第一个Object是差不多的,但是需要注意的是后续无法对这个变量进行修改

1
2
3
4
5
// 测试
let a: {} = {a:123}
// 报错: Property 'age' does not exist on type '{}'
a.age = 18
Object类型也会报错

Interface

定义接口类型 ; 属性不能多也不能少

* 任意类型

  • 一旦定义了任意类型,那么interface中确认的属性和可选的属性类型都必须是它的类型的子集,不然报错

  • 继承的父类的类型也必须是它的子类型,不然会报错

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
81
82
83
84
85
// 属性不能多也不能少
interface ICaoqin {
name: string
age: number
}
let a: ICaoqin = {
name: 'caoqin',
age: 18
}
//如果遇到重名,会进行重合
interface ICaoqin {
study: boolean
}
let b: ICaoqin = {
name: 'caoqin',
age: 18
study: false
}

// 任意key值,索引签名
interface ICaoqin {
name: string
age: number
// 这个是任意key值,只会校验前两个,其他就不管了,可以解决后台返回过于杂乱
[propName: string]: any
}

let a: ICaoqin = {
name: 'caoqin',
age: 18,
//下面的属性是不会进行校验的
study: true,
b: 1
}

// 可选类型,实现接口可以有可以无的类型
interface ICaoqin {
name: string
age?: number
}

let a: ICaoqin = {
name: 'caoqin'
}

// 只读属性设置,不允许修改,常用于设置id
interface ICaoqin {
name: string
age?: number
readonly cb: () => boolean
}

let a: ICaoqin = {
name: 'caoqin',
cb: () => {
return false
}
}
// 报错 Cannot assign to 'cb' because it is a read-only property.
a.cb = () => {
return true
}

//接口继承 类似于重合,可以继承多个
interface ICaoqin extends B {
name: string
age?: number
}
interface B {
xxx: string
}
let a: ICaoqin = {
xxx: "sss",
name: 'caoqin',
}

// interface定义函数类型
interface IFn {
// ()里面定义的是函数参数类型,:定义的是函数返回值类型
(name: string, age: number): number[]
}

const fn: IFn = function() {
return [123]
}

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 普通定义
number[]
Array<boolean>
// 定义一维对象数组类型
interface X {
name: string,
age: number
}
const arr: X[] = [{name: 'caoqin', age: 18}, {name: 'Apo', age: 18}]

// 定义二维数组类型 套娃
number[][]
Array<Array<boolean>>

// 大杂烩数组
any[]
let arr:[number, string, boolean, {}] = [1, "asd", true, {}] // 元组类型

// IArgument类型

函数扩展

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
// 函数定义类型和返回值 | 箭头函数定义类型和返回值
function foo(name: string): string {
return "caoqin"
}
const add = (a: number, b: number): number => a + b

// 函数的默认参数 | 函数可选参数 注意:两者不可以同时出现
function foo(name: string = 'caoqin'): string {
return "caoqin"
}
foo()
function foo(name?: string): string {
return "caoqin"
}
foo()

//参数是一个对象该如何定义
interface IUser {
name: string
age: number
}
function foo(user: IUser): IUser {
return user
}
foo({name: 'caoqin', age: 18})

// 函数this类型 ts中可以定义this的类型,在js中无法使用,必须是第一个参数定义this类型
interface IObj {
user: number[]
// 第一个参数指定this,第二个才是需要传递的参数
add: (this: IObj, num: number) => void
}

let obj: IObj = {
user: [1, 2],
add(this: IObj, num: number) {
this.user.push(num)
},
}

// 函数重载

联合类型 | 类型断言 | 交叉类型

| : 联合类型

&: 联合类型,相当于extends,两个都要满足条件

as:类型断言;只能欺骗typescript编译器,但是无法避免运行时错误,数据类型无该数据依旧会报错

内置对象

ecma: Number Date Rgxp Error XMLHttpRequest

const date:Date = new Date() === const date= new Date()

Class类

类型约束:通过实现接口 implements,要实现接口里面所有的方法

继承: extends 一定要写在实现接口前面

修饰符:readonly 、 private(内部使用) 、 public(哪里都能用) 、 protected(子类和内部使用)

super:指向父类,可以理解为super是父类的一个实例,可以调用父类中的方法:父类的prototype.constructor.call

静态方法(static):使用实例本身(也就是类本身)调用方法,就是静态方法如Promise.all(),他只能通过类本身调用,类new出来的实例无法进行调用;静态方法的this只能指向静态方法;static只能调用static方法和属性,不能调用其他的

get 、set:get可以拦截读取值的操作然后对这个值进行操作;set可以拦截设置值的操作,对值进行操作

get和set操作

抽象类

abstract所定义的类,叫做抽象类,抽象类中实现的方法叫做抽象方法,只能描述不能进行实现

抽象类不能进行实例化

使用:使用派生类实现抽象类,在实现里面的抽象方法就可以了

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
abstract class Ref {
name: string
constructor(name: string = 'aaa') {
this.name = name
}

getName() : string {
return this.name
}
abstract init(name: string): void
}
// Cannot create an instance of an abstract class.
// const ref = new Ref()
//没有实现抽象类方法时:Non-abstract class 'React' does not implement inherited abstract member 'init' from class 'Ref'
class React extends Ref {
constructor() {
super()
}
// 实现该抽象方法就不会报错
init(name: string) {

}
setName(name: string) {
this.name = name
}
}
const react = new React()
react.setName('aaaa')
console.log(react.getName());

元组类型

元组类型push越界的时候他只会推断成元组之前类型的联合类型;元组是可以进行更改的;可以用来描述excel,固定表头

枚举类型 | enum

不设置值从0开始,设置值之后会依次递增

类型推论 | 类型别名

类型推论:会根据你赋值来推导当前类型;如果定义变量但是没有赋值,他会推断为any类型

类型别名:type s = string | number let a: s = 123

type和interface主要区别在于type无法实现extends;interface 无法在外面定义联合类型,type可以写联合类型;type遇到重名不会合并;extends在 type里面是包含的意思

never

通常同来表示 不存在的状态或者无法达到预期的状态

type A = number & string 没有哪个类型都能满足这两个条件,所以A推断出来是never类型

never类型在联合类型中是会忽略掉的

兜底逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type A = '唱' | '跳' | 'rap'

function Foo(value: A) {
switch (value) {
case '唱' :
break
case '跳' :
break
case 'rap' :
break
// 兜底逻辑,避免别人接手代码的时候不知道为什么实现不了
default:
const err:never = value
break
}
}

Symbol

1
2
3
4
5
6
7
let a = Symbol(1)
let b = Symbol(2)
console.log(a === b); // false,内存地址是不一样的
// true,Symbol for是全局symbol有没有组注册过这个key,如果有,就直接返回,没有才会创建一个
console.log(Symbol.for("aaa") === Symbol.for("aaa"));

// 主要应用场景:解决属性key重复的问题;for in不能读到Symbol,Object.keys(obj)也读不到key;Object.getOwnPropertySymbol()来对symbol进行读取;Reflect.ownKeys()既能拿到普通的值,也能拿到Symbol的值

生成器 迭代器

迭代器Iterator:set、map、arguments(类数组,不具备forEach等属性)、NodeList

生成器generator是特殊的迭代器iterator

generator使用

1
2
3
4
5
6
7
8
9
10
// es6新增迭代器set map weakset weakmap
// 天然去重,可以对数组进行去重,但只对number和string有效果
let set: Set<number> = new Set([1, 1, 2, 2, 3, 3 ])
console.log(set); // Set(3) { 1, 2, 3 }

// map存放key value;map和对象的区别在于,它的key可以使用引用类型,应用场景在当key作为引用类型时可以使用
let b: Map<any, any> = new Map()
const Arr = [1, 2, 3]
b.set(Arr, 3)
console.log(b.get(Arr)); // 3

泛型

泛型约束

1
2
3
4
5
6
7
8
9
10
11
12
13
// 泛型类型约束
function foo<T> (a: T extends number[]) {
console.log(a);
}
//
let obj = {
name: 'caoqin',
age: 18
}
function ob<T extends object, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
ob(obj, 'name')

tsconfig.json

初始化tsconfig.json文件: tsc –init

tsconfig.json:TypeScript使用tsconfig.json文件管理工程配置,例如你想包含哪些文件和进行哪些检查。

namespace

在ts文件当中,如果编写ts内容,默认里面的数据都是全局的,可以导出变量 **export {}**,把一个ts文件当作是一块空间,空间之间互不干扰;或者命名空间 namespace A{},调用里面的属性: A.a [使用场景:旧的typescript]

三斜线指令

在typescript2.0版本开始,三斜线指令被弃用了,推荐使用ES6模块语法和import语句

声明文件d.ts

declare

一般比较常用的库它本身会携带声明文件,如果没有的话,一些常用的库社区可能会有相应的声明文件,下载安装即可, 以express为例,点进去是index.js文件,不是声明文件,说明库本身不包含声明文件,可以看一下编译器的提示,如果有社区版就直接安装即可,安装在node_modules/@types,如果社区没有提供,建议换个库使用,自己编写一个d.ts文件不现实

Mixins混入


TypeScript
http://example.com/2023/07/05/TypeScript/
作者
Caoqin
发布于
2023年7月5日
许可协议