Typescript教程

1. TS简介

1.1. typescript是什么?

以javascript为基础构建的语言
可以在任何支持javascript的平台中执行
一个javascript的超集
typescript扩展了javascript,并添加了类型
TS不能被JS解析器直接执行,需要经过编译成javascript后被JS解析器执行。

1.2. Typescript增加了什么?

  • 类型
    • 保证原有类型的基础上增加了一些新类型
  • 支持ES的新特性
  • 添加ES不具备的新特性
  • 丰富的配置选项
  • 强大的开发工具

2. TS开发环境搭建

  1. typescript开发环境搭建

3. TS的类型声明

  • 类型声明

    • 类型声明是TS非常重要的一个特点

    • 通过类型声明可以指定TS中变量(参数, 形参)的类型

    • 指定类型后, 当为变量赋值时, TS编译器会自动检查值是否符合类型声明, 符合则赋值, 否则报错。

    • 简而言之, 类型声明给变量设置了类型, 使得变量存储某种类型的值。

    • 语法

      1
      2
      3
      4
      5
      6
      let  变量:类型;
      let 变量:类型 = 值;

      function fn(参数:类型, 参数:类型) :类型 {

      }
  • 自动类型判断

    • TS拥有自动类型判断机制
    • 当对变量的声明和赋值是同时进行的, TS编译器会自动判断变量的类型
    • 所以如果你的变量的声明和赋值是同时进行的,可以省略掉类型声明

4. TS中的类型

  • TS基本类型
类型例子描述
number1, -33, 2.5任意数字
string任意字符串
booleantrue, false布尔值true或false
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值(或者undefined)
never没有值不能是任何值
object{name: ‘孙悟空’}任意JS对象
tuple[4,5]元素,TS新增类型,固定长度数组
enumenum{A, B}枚举,TS新增类型
  • number
1
2
3
4
5
let  decimal:  number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010
let octal: number = 0o744
let big: bigint = 100n;
  • 字面量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//这种不常用
let a: 10;
a = 10;
a = 11; // 编译报错, 因为a声明时已经指定为字面量10

//常用
let b: "male" | "female"
b= "male"
b= "female"
b="hello" // 编译报错

let c: boolean | string
c = true;
c = 'true';
  • any

显式声明变量为any

1
2
3
4
5
//  any  表示的是任意类型, 一个变量设置类型为any后相当于该变量关闭了TS的类型检测
let d: any
d = 10;
d = 'hello'
d = true;

隐式声明变量为any

1
2
3
4
5
//  any  表示的是任意类型, 一个变量设置类型为any后相当于该变量关闭了TS的类型检测
let d: any
d = 10;
d = 'hello'
d = true;
  • unknown

unknown表示未知类型的值

any 和 unknown 的差别

1
2
3
4
5
6
7
8
let  d: any

d = true

let s: string

s = d; // 这里不会报错

1
2
3
4
5
6
7
8
let  d: unknown

d = true

let s: string

s = d; // 这里会报错

解决办法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let  d: unknown

d = true

let s: string

d= 'hello';

if(typeof e === "string") {
s = d; // 这里不会报错
}
或者

//使用断言
s = d as string;
或者
s = <string>d

  • void

  • never

  • object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

let a :object;

a = {}
a = function() {
}

// {} 用来指定对象中可以包含哪些属性
// 语法: {属性名: 属性值}
let b: {name: string}

b = {name: '孙悟空'}

属性上加上?, 表示属性是可选的

let b: {name: string, age?: number}

b = {name: '孙悟空', age: 18}

// 对象里有name属性
let c: {name: string, [propName: string]: any}
  • Function
1
2
3

let d: (a:number, b: number) => number;

  • Array
1
2
3
4
5
6
let  e: string[];
e = ['a', 'b', 'c']

let g: Array<number>

g = [1,2,3]
  • tuple 元组
1
2
3
let  h: [string,  string]

h = ['hi', 'world']
  • enum 枚举
1
2
3
4
5

enum Gender {
Male,
Female
}

补充

//& 同时

1
let  j: {name: string}  &  {age: number}

// 类型的别名

1
type  myType = 1|2|3|4|5  ;

5. TS编译选项

tsconfig.json

  • include
1
2
3
"include": {
"./src/**/*"
}
  • exclude
1
2
3
"exclude": {
"./src/hello/**"
}
  • compilerOptions

    • target

      • 选项
        • es3
        • es5
        • es6
        • es2015(ES6)
        • es2016
        • es2017
        • es2018
        • es2019
        • es2020
        • esnext (ES最新版本)
    • module

      • 指定使用的模块化的解决方案

        • 选项
          • es6
          • es2015
          • es2020
          • es2020
          • esnext
          • umd
          • system
          • amd
          • commonjs
          • none
      • lib

        1
        lib: []
      • outDir

      • outFile

      • allowJs

        • 是否对JS文件进行编译
      • checkJs

        • 是否检测js代码的语法
      • removeComments

        • 编译过程中是否删除注释
      • noEmit

        • 不生成编译后的文件
      • noEmitOnError

        • 当有错误的时候不生成编译后的文件
  • 语法检测相关选项

    • alwaysStrict

6. 面向对象简介

面向对象是程序中一个非常重要的思想, 因被很多同学理解成一个比较难, 比较深奥的问题, 其实不然, 面向对象很简单, 简而言之就是程序之中所有的操作都需要通过对象来完成。

  • 举例来说:
    • 操作浏览器要使用window对象
      • 操作网页要使用document对象
      • 操作控制台要使用console对象

一切操作都要通过对象, 也就是所谓的面向对象, 那么对象到底是什么呢? 这就要先说到程序是什么, 计算机程序的本质是对现实事物的抽象, 抽象的反义词是具体, 比如: 照片是对一个具体的人的抽象, 汽车模型是对具体的汽车的抽象等等。 程序也是对事物的抽象。
在程序中我们可以表示一个人, 一条狗, 一把枪, 一颗子弹等等所有的事物。 一个事物到了程序中就变成了一个对象。
在程序中所有的对象都被分成了两个部分数据和功能, 以人为例, 人的姓名, 性别, 年龄, 身高, 体重等属于数据, 人可以说话, 走路, 吃饭, 睡觉这些属于人的功能。 数据在对象中成为属性, 而功能就被称为方法。 所以简而言之, 在程序中一切皆是对象。

7. 类的简介

  1. 类(class)

要想面向对象, 操作对象, 首先要拥有对象, 那么下一个问题就是如何创建对象。 要创建对象, 必须首先定义类, 所谓的类可以理解为对象的模型, 程序中可以根据类创建指定的对象, 举例来说: 可以通过Person类来创建人的对象, 通过Dog类来创建狗的对象,
通过Car类来创建汽车的对象, 不同的类可以创建不同的对象。

  • 定义类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      class  类名  {

    属性: 类型;

    constructor(参数: 类型) {

    }

    方法名() {

    }
    }
    • 示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      class  Person  {
      name: string;
      age: number;

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

      introduce() {
      console.log("my name is "+ name + "I am "+age+" old")
      }
      }
      • 使用类
      1
      2
      3
      4
      5
      6
            const  zhangsan = new  Person("ZhangSan",  20);
      const lisi = new Person("lisi", 22);

      zhangsan.introduce();
      lisi.introduce();

      • 定义实例属性

        1
        2
        name: string;
        age: number;
        • 定义实例方法
        1
        2
        3
        sayHello(){
        console.log("hello")
        }
        • 定义类属性属性
        1
        static attrName: string;
        • 定义类方法
        1
        2
        3
        static  sayHi()  {
        console.log("Hi")
        }
      • 定义只读属性

        1
        2
        readonly  name: string;

      • 构造函数

        1
        2
        constructor()  {  }

8. 构造函数和this

9. 继承简介

1
2
3
4
5

class Dog extends Animal {

}

9.1. 方法的重写

9.2. super关键字

10. 抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

abstract class Animal {
name: string;

constructor(name:string){
this.name = name;

}

sayHello() {
console.log("动物在叫")
}

}

抽象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14

abstract class Animal {
name: string;

constructor(name:string){
this.name = name;
}

// 定义一个抽象方法
// 抽象方法使用abstract开头, 没有方法体
// 抽象方法只能定义在抽象类中, 子类需要对方法进行实现
abstract sayHello(): void;
}

11. 接口

11.1. 定义接口

1
2
3
4
5
6
7
8
9
10
11
12
/*
* 接口可以在定义类的时候限制类的结构
* 接口中的所有的属性都不能有实际值
* 接口只定义对象的结构, 而不考虑实际值
* 在接口中所有的方法都是抽象方法
*/
interface myInterface {
name:string;
age: number;
sayHello(): void;
}

11.2. 实现接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* 定义类时, 可以使类去实现一个接口,
* 实现接口就是使类满足接口的要求
**/

class MyClass implements myInterface {
name: string;

constructor(name:string) {
this.name = name;
}

sayHello() {
console.log('hello everyone')
}
}

12. 属性的封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class Person {
name: string;
age: number;

constructor(name:string, age: number) {

this.name = name;
this.age = age;
}
}
const per = new Person('孙悟空', 18);

/*
* 现在属性时在对象中设置的, 属性可以任意被修改,
* 属性可以任意被修改会导致对象中的数据变得非常不安全
**/
per.name = '猪八戒'
per.age = -38

console.log(per);


属性的可见性

public, private, protected

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

class Person {

/*
* public 修饰的属性可以在任意位置访问(修改) 默认值
* private 私有属性, 私有属性只能在类内部进行访问
* - 通过在类中添加方法使得私有属性可以被外部访问
* protected 受保护的属性或方法,只能在子类中访问
**/
private name: string;
private age: number;

constructor(name:string, age: number) {

this.name = name;
this.age = age;

}

// 定义方法, 用来获取name属性
getName() {
return this.name;
}

// 定义方法, 用来设置name属性
// 有了
setName(value: string) {
}

}
const per = new Person('孙悟空', 18);

/*
* 现在属性时在对象中设置的, 属性可以任意被修改,
* 属性可以任意被修改会导致对象中的数据变得非常不安全
**/
per.name = '猪八戒'
per.age = -38

console.log(per);


12.1. ts中实现getter setter的独特方式

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

class Person {

private _name: string;
private _age: number;

constructor(name:string, age: number) {

this._name = name;
this._age = age;

}

// 定义方法, 用来获取name属性
get name() {
return this._name;
}

// 定义方法, 用来设置name属性
// 有了
setName(value: string) {
}

}
const per = new Person('孙悟空', 18);

/*
* 现在属性时在对象中设置的, 属性可以任意被修改,
* 属性可以任意被修改会导致对象中的数据变得非常不安全
**/
per.name = '猪八戒'


console.log(per);


12.2. 简化写法

13. 泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

//泛型的定义
function fn<T> (a: T): T {

}

// 泛型的使用:
// 可以直接调用具有泛型的函数

fn(10) //不指定类型, TS可以自动对类型进行推断

//也可以明确指定参数类型
fn<string> ('hello')


//多泛型的定义

1
2
3
4
5
6
7
8
9
function  fn2<T,  K>  (a: T,  b: K): T  {
console.log(b)
return a;
}

// 限定泛型的类型
function fn3<T extends Inter>(a: T): number {
return a.length;
}

泛型类

1
2
3
4
5
6
7
8
9
10
11
class  MyClass<T>  {
name: T;
constructor(name: T) {

this.name = name;
}
}

使用

const mc = new MyClass<string>('孙悟空');

14. 参考

尚硅谷typescript教程

TypeScript 语言简介