TypeScript学习

什么是TypeScript

融合了后端面向对象思想的超级版的javaScript 语言。

环境搭建

1
2
3
npm init -y
yarn add typescript -D
tsc --init

优势

  • 优势1:编译时静态类型检测:函数或方法传参或变量赋值不匹配时,会出现编译错误提示 ,规避了开发期间的大量低级错误,省时,省力。
  • 优势2:自动提示更清晰明确。
  • 优势3:引入了泛型和一系列的 TS 特有的类型。
  • 优势4:强大的 d.ts 声明文件:声明文件像一个书的目录一样,清晰直观展示了依赖库文件的接口,type类型,类,函数,变量等声明
  • 优势5:轻松编译成 JS 文件:即使 TS 文件有错误,绝大多数情况也能编译出 JS 文件。
  • 优势6:灵活性高: 尽管 TS 是一门 强类型检査语言,但也提供了 any 类型 和 as any 断言,这提供了 TS 的灵活度。

类型注解与推导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 类型注解
let data: number = 3


// 类型推导
let money = 30


interface Student {
name: string,
age: number
}

let stu: Student = {
name: "",
age: 0
}

export {} // 这句话的作用是 当前变量的作用于属于这个ts文件

编译与优化

tsconfig.json文件里 修改 “rootDir”: “./src” 与 “outDir”: “./dist” 源文件与编译后文件

然后在项目根目录 输入 tsc 执行编译, src里面的文件都会按照commonjs规范编译出dist里的文件

常用的24种TS类型

基本类型:

number, string ,boolean, symbol, null, undefined

根类型: 所有其他数据类型的父类

Object, {} // 大括号是Object的简写

对象类型:

Array, object, function

枚举:

enum

其他特殊类型:

any,unknown,never,void,元组(tuple),可变元组

合成类型:

联合类型,交叉类型

字面量数据类型:

枚举的定义,分类,取值方式

用来存放一组固定的常量的序列 包括字符串枚举和数字枚举

any与unknown

相同点: any 和 unknown 可以是任何类的父类,所以任何类型的变量都可以赋值给 any 类型或 unknown类型的变量。

不同点1:any 也可以是任何类的子类,但 unknown 不可以,所以 any 类型的变量都可以赋值给 其他类型的变量。

不同点2:不能拿 unknown 类型的变量来获取任何属性和方法,但 any 类型的变量可以获取任意名称的属性和任意名称的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// any与unknown 是子类
let str:string = "hello world"
let data: any = str
let data2: unknown = str
let data3: any = undefined


let array:any = ["a", "b"]
let array2:Array<string> = array

// let array3:unknown = ["a", "b"]
// let array4:Array<string> = array3 //错误

function getData(data:any):any{
return data.name
}

// function getData2(data:unknown):string{
// return data.name // 错误 无法获取属性
// }

接口

另一种定义对象类型的类型

可以为多个同类别的类提供统一的方法和属性申明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface Product {
name: string
price: number
account: number
buy(): void
}

let p: Product = {
name: "",
price: 0,
account: 0,
buy: function (): void {
throw new Error("Function not implemented.")
}
}

// 接口继承 继承了Product的所有属性
interface Student extends Product {
id: number
}

可索引签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Product {
name: string
price: number
account: number
[x: string]: any // 索引签名的值需要兼容其他属性
// [y: string]: number
}

let p: Product = {
name: "",
price: 0,
account: 0,
info: "hello", // 索引签名 可以是任意类型
100: "hello",
buy: function (): void {
throw new Error("Function not implemented.")
}
}

null 和 undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const str: string = "abc"
console.log(str.length)

// let str1: string
// console.log(str1) // 无法打印

let str2: string | undefined = undefined
console.log(str2)

// let str3: string = undefined // 无法赋值
// console.log(str3)

function fn(data?: string) { // data类型为string | undefined
// 把data解析为string | undefined类型
}
fn()

// any, unkonwn, undefined 可以接受undefined
// any, unkonwn, null 可以接受null
let data: any = undefined

函数和函数类型 rest参数

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

function info(name: string, age: number): number {
console.log(name, age)
return 3
}
info("hello", 3)


let info2 = function (name: string, age: number): number {
console.log(name, age)
return 3
}
info2("hello", 3)


let info3: (name: string, age: number) => number =
function (name, age): number {
console.log(name, age)
return 3
}
info3("hello", 3)


type InfoFunType = (name: string, age: number) => number
let info4: InfoFunType =
function (name, age): number {
console.log(name, age)
return 3
}
info4("hello", 3)

function info5(name: string, age: number, ...rest: any): number {
console.log(name, age, rest)
return 3
}
info5("", 23, "123", 456, 789)

元组

满足以下3点的数组就是元组

(1)在定义时每个元素的类型都确定

(2)元素值的数据类型必须是当前元素定义的类型

(3)元素值的个数必须和定义时个数相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let salary: [string, number] = ["hello", 100]


// 数组与数组元素同时为只读
const arr = [10, 20, 30, 40, 50] as const
// arr[0] = 100 // 不能修改



// 可变元组
let arr1: [number, ...string[]] = [1, "hello", "world"]

// 可变元组结构
let [age, ...rest]: [number, ...string[]] = [1, "hello", "world", "world"]
console.log(age, rest)
let [age1, name, ...rest1]: [age1_: number, name_: string, ...rest_: string[]] = [1, "hello", "world", "world"]
console.log(age, rest)

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

class People {
name: string
age: number;
addr: string;
constructor(name: string, age: number, addr: string) {
this.name = name;
this.age = age;
this.addr = addr;
}
}

// let p = new People("张三", 18, "北京")
// console.log(p)


// 类单例模式
class People2 {
name: string
age: number;
addr: string;

static people: People2
static getInstance(): People2 {
if (!People2.people) {
People2.people = new People2("李四", 20, "上海")
}
return People2.people
}

constructor(name: string, age: number, addr: string) {
this.name = name;
this.age = age;
this.addr = addr;
}
sayHi() {
console.log("Hi")
}
}

const p2 = People2.getInstance()
const p3 = People2.getInstance()
console.log(p2 === p3)

泛型

具有以下特点的数据类型叫泛型

特点一:定义时不明确使用时必须明确成某种具体数据类型的数据类型。【泛型的宽泛】

特点二:编译期间进行数据类型检查的数据类型。【泛型的严谨】

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

interface Ref<V> {
value: V
}

let ref: Ref<string> = { value: "23" }

type Student = { name: string, age: number }

let ref2: Ref<Student> = {
value: {
name: "wangwu",
age: 23
}
}

ref.value
ref2.value.name

class ArrayList<T> {
arr: Array<T>
constructor() {
this.arr = []
}

add(ele: T) {
this.arr.push(ele)
}
get(index: number): T {
return this.arr[index]
}
}

class MyArrayList<T = any> { // 泛型默认值
arr: Array<T>
constructor() {
this.arr = []
}

add(ele: T) {
this.arr.push(ele)
}
get(index: number): T {
return this.arr[index]
}
}

let arr = new ArrayList<string>()

function quickSort<E> (arr: E[]) : Array<E> {
return arr
}