• TypeScript学习记录


    一、TS开发环境的搭建

    1、下载并安装node.js

    2、使用npm全局安装typeScript

    • 进入命令行
    • 输入:npm i -g typescript

    3、创建一个ts文件

    4、使用tsc对ts文件进行编译

    • 进入命令行
    • 进入ts文件所在目录
    • 执行命令:tsc 文件名.ts

    二、TS基本变量

    1、基础数据类型

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

    类型声明给变量设置了类型,使用变量只能存储某种类型的值

    语法:

    let 变量:类型

    let 变量:类型=值

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

            ......

    }

    1. let a: number = 2
    2. let str: string = '你好'
    3. a = 3
    4. function fn(a: string) {
    5. console.log(a);
    6. }
    7. fn('123')
    8. // 布尔类型:boolean
    9. let flag = false;
    10. // flag=123 报错
    11. flag = true;
    12. // 数字类型:number
    13. let num = 10; //十进制
    14. let num1 = 0b1010; // 二进制
    15. let num2 = 0o12; // 八进制
    16. // 字符串类型:string
    17. let str = '123';
    18. str = '';
    19. // undefined和null
    20. let u = undefined;
    21. let n = null;
    22. // undefined和null可以作为其他类型的子类型
    23. // 可以把undefined和null赋值给其他类型的变量
    24. let c = undefined;
    25. let str1 = null;

    2、数组和对象类型

    1. // 数组
    2. // 定义数组一:
    3. let arr1: number[] = [1, 2, 3]
    4. arr1 = [3, 4, 5]
    5. // 定义数组二:泛型
    6. let arr2: Array = [12, 13, 14]
    7. // 对象
    8. // object表示非原始类型,除了number,string,boolean之外的类型
    9. let obj: object = {}
    10. // 字面量
    11. // obj=123 报错
    12. obj = { name: '张三' }
    13. obj = undefined
    14. obj = null
    15. obj = []
    16. obj = new String()
    17. obj = String

    3、any和void类型

    any:任何类型

    1. let h: any = 123
    2. h = false
    3. h = '泥嚎'
    4. h = {}
    5. h = []
    6. let newArr: any[] = [100, 2, '你好', true]
    7. // console.log(newArr[0].split('')); ts编译不报错,但是split是字符串的操作方法,100并不是字符串

    void:空值,表示没有任何返回值的函数

    1. function fn(): void {
    2. console.log(123);
    3. }
    4. console.log(fn());

    4、类型推断

    ts在没有明确指定类型的时候推测一个类型

    有两种情况:

    • 定义变量的时候,直接给变量赋值,则定义类型为对应类型
    • 定义变量的时候没有赋值,则定义为any类型
    1. let t = 123 // ts将t定义成一个number类型,通过类型推断
    2. // t='' 报错
    3. let g; // 定义变量的时候没有赋值,则定义为any类型
    4. g = 123
    5. g = true
    6. g = ""
    7. g = []
    8. g = {}

    5、联合类型

    表示取值可以为多种类型中的一种

    1. // flag true 1 false 0
    2. let f: boolean | number | string = true // 此时只能访问联合类型的所有类型共有的属性或方法
    3. f = 123 // 再次赋值,走类型推断,给变量定义一个类型,此时就可以使用该类型的属性或方法
    4. f = '123'
    5. f = false
    6. // console.log(f.split(''));

    6、接口

    对象类型

    接口是对行为的抽象,用于对对象形状进行描述,可以理解为一种约束

    接口的首字母一般大写

    定义的变量比接口多或少一些属性都是不被允许的

    可选属性:有时不需要完全匹配一个形状可以使用可选属性:?表示可选属性,定义对象?的属性可有可无

    ?表示可选属性,定义对象?的属性可有可无

    任意属性:有时我们希望一个接口允许有任意的属性,一旦定义了任意属性,那么任意属性和可选属性的类型都必须是它的类型的子集

    [propName:string]:any

    一个接口中只能定义一个任意属性,如果接口中有多个类型的属性,则可以在任意属性中使用联合类型

    [propName:string]:number | string | boolean

    只读属性:可以用readonly定义只读属性

    1. interface IPerson {
    2. readonly id: number,
    3. name: string,
    4. age: number,
    5. sex?: string,
    6. [propName: string]: number | string | boolean
    7. // [propName: string]: any
    8. }
    9. let p: IPerson = {
    10. id: 1,
    11. name: '张三',
    12. age: 12,
    13. height: 168,
    14. width: true
    15. }
    16. // p.id=2 报错 因为id是只读属性

    数组类型(不常用)

    1. interface INewArray {
    2. [index: number]: number // 任意属性,index表示数组中的下标
    3. }
    4. let arr: INewArray = [1, 2, 3, 4]

    函数类型

    (参数:类型,...):返回值的类型

    1. interface ISearchFunc {
    2. // (参数:类型,...):返回值的类型
    3. (a: string, b: string): boolean
    4. }
    5. // 参数,返回值
    6. const fun1: ISearchFunc = function (a: string, b: string): boolean {
    7. return a.search(b) !== -1
    8. }
    9. console.log(fun1('123', '1'));

    接口继承接口

    接口可以继承其他多个接口,再让类实现接口

    1. interface IRun {
    2. run()
    3. }
    4. interface ISwim {
    5. swim()
    6. }
    7. // 接口可以继承其他多个接口,再让类实现接口
    8. interface IActive extends IRun, ISwim {}
    9. class I implements IActive {
    10. run() {
    11. console.log('run');
    12. }
    13. swim() {
    14. console.log('swim');
    15. }
    16. }

    接口继承类

    接口继承类中的实例属性和实例方法

    7、函数

    定义函数的方式

    参数a和b都是Number类型

    :number表示该函数的返回值为number类型

    1. function add(a: number, b: number): number {
    2. return a + b
    3. }
    4. let cc: number = add(1, 2)
    5. console.log(cc);
    6. // 函数表达式:匿名函数
    7. let add2 = function (a: number, b: number): number {
    8. return a + b
    9. }
    10. console.log(add2(1, 2));
    11. // 函数完整的写法
    12. let add3: (a: number, b: number) => number = function (a: number, b: number): number {
    13. return a + b
    14. }

    可选参数和默认参数

    可选参数 ?

    1. let getName1 = function (x: string = "李", y?: string): string {
    2. return x + y
    3. }

    必选参数不能位于可选参数后面

    默认参数可以放在必选参数或可选参数后面

    1. let getName2 = function (x: string, y?: string, z: string = "李"): string {
    2. return x + y + z
    3. }

    8、剩余参数和函数重载

    ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数)

    1. function fn(x: string, y: string, ...args) {
    2. console.log(x, y, args);
    3. }
    4. console.log(fn('1', '1', 1, 2, 3, 4, 5));

    函数重载:函数名相同,形参不同的多个函数

    没有使用函数重载时:有一个缺点,就是不能够精确的表达,输入为数字的时候,输出也应该为数字,输入为字符串的时候,输出也应该为字符串。

    使用函数重载可以解决这个问题:

    可以使用重载定义定义多个newAdd的函数类型

    9、类型断言

    类型断言:可以手动指定一个类型

    两种语法:

    • 变量 as 类型
    • <类型>变量

    当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型中共有的属性或方法

    而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法

    比如:定义一个函数,获取到一个数字或字符串的长度

    解决方法:使用类型断言

    1. function getLength(x: string | number): number {
    2. if ((x as string).length) {
    3. return (x).length
    4. } else {
    5. return x.toString().length
    6. }
    7. }
    8. console.log(getLength(90));

    将任何一个类型断言为any类型,any类型可以访问所有的属性和方法,但是它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用as any

    (window as any).a = 10

    将any断言为一个具体的类型

    a1被断言为number类型。a2此时被断言为string类型

    1. function abc(x: any, y: any): any {
    2. return x + y
    3. }
    4. let a1 = abc(1, 2) as number
    5. let a2 = abc('1', '2') as string
    6. console.log(a1);
    7. console.log(a2);

    10、类型别名

    通过类型type给类型起别名

    1. type s = string // 通过type给类型起别名
    2. let str2: s = '123'
    3. str = '456'
    1. let a3:string|number|boolean=123
    2. let b1:string|number|boolean=true

    常用于给联合类型起别名,可以写为:

    1. type all = string | number | boolean
    2. let a3: all = 123
    3. let b1: all = true

    11、字符串字面量类型

    用来约束取值只能是某个字符串中的一个

    比如:张三,张三丰,张大炮,names只能为其中的一个

    1. type stringType = '张三丰' | '张三' | '张大炮'
    2. // let names: stringType = '张三1' 报错
    3. let names: stringType = '张三'

    12、元祖(Tuple)

    元祖(Tuple)合并了不同类型的对象

    1. let arr4: number[] = [1, 2, 3, 4]
    2. // 数值和字符串
    3. // 元祖(Tuple)合并了不同类型的对象
    4. let Tarr: [number, string] = [123, '123']
    5. // 添加内容的时候需要是number或string类型
    6. Tarr.push('456')
    7. Tarr.push(123)
    8. // Tarr.push(true) 报错

    13、枚举

    枚举Enum

    使用枚举类型给一组数据赋值名称,可以通过名称拿取值,也可以通过值拿取名称

    手动赋值注意:尽量不要写一些重复值,会覆盖

    1. enum NumberType {
    2. one = 1, // 手动赋值,如果没有赋值,第一个参数默认为0,后面的值会根据前一个值递增+1
    3. two,
    4. three,
    5. four
    6. }
    7. console.log(NumberType.one); //1
    8. console.log(NumberType.two); //2

    常数枚举

    常数枚举是使用const enum定义的枚举类型

    常熟枚举与普通枚举的区别是,他会在编译阶段被删除,并且不能包含计算成员

    1. const enum obj1 {
    2. o, b, j
    3. }
    4. console.log(obj1.o); // 0
    5. console.log(obj1.j); // 2

    外部枚举

    外部枚举(Ambient Enums)是使用declare enum定义的枚举类型

    declare定义的类型只会用于编译时的检查,编译结果中会被删除

    1. declare enum ABC {
    2. a, b, c
    3. } // 编译过程中会被删除
    4. console.log(ABC.a);

    14、类

    属性和方法

    类:描述了所创建的对象共同的属性和方法

    1. class Person {
    2. name: string
    3. age: number
    4. constructor(name: string, age: number) {
    5. this.name = name
    6. this.age = age
    7. }
    8. sayHi(str: string) {
    9. console.log('hi' + str);
    10. }
    11. }
    12. let q = new Person('张三', 18) // new的时候,会执行类中构造方法constructor
    13. q.sayHi('张三')

    类的继承

    通过继承扩展现有的类

    继承:类与类之间的关系

    类与类之间存在继承关系,通过extends进行继承

    子类可以调用父类的方法,通过super

    1. class Animal { // 父类
    2. name: string
    3. age: string
    4. constructor(name: string, age: string) {
    5. this.name = name
    6. this.age = age
    7. }
    8. sayHi(str: string) {
    9. console.log('hi' + str);
    10. }
    11. }
    12. // 子类
    13. class Dog extends Animal {
    14. constructor(name: string, age: string) {
    15. // 调用父类构造函数,使用super
    16. super(name, age)
    17. }
    18. // 可以调用父类的方法,还可以重写父类的方法
    19. sayHi(str: string) {
    20. console.log('我是dog类的shyHi方法');
    21. super.sayHi('狗子') // 可以用super调用父类的方法
    22. }
    23. }
    24. const aaa = new Animal('小猫', '三岁')
    25. aaa.sayHi('小猫')
    26. const ddd = new Dog('小狗', '一岁')
    27. ddd.sayHi('可爱的狗子')

    存取器

    存取器:可以帮助我们控制对象成员的访问

    1. class Name {
    2. firstName: string
    3. lastName: string
    4. constructor(firstName: string, lastName: string) {
    5. this.firstName = firstName
    6. this.lastName = lastName
    7. }
    8. // 设置存取器
    9. // 读取器--->用来读取数据
    10. get fullName() {
    11. return this.firstName + '-' + this.lastName
    12. // return '张三'
    13. }
    14. // 设置器--->用来设置数据
    15. set fullName(value) {
    16. let names = value.split('-')
    17. this.firstName = names[1]
    18. this.lastName = names[0]
    19. }
    20. }
    21. const n3 = new Name('张', '大炮')
    22. // console.log(n3);
    23. n3.fullName = '张-三丰' // 没有设置器时fullName是只读的
    24. console.log(n3.fullName);

    静态成员

    静态方法、静态属性

    只属于类自己的属性和方法

    1. class A {
    2. static name1: string
    3. // constructor(name: string) {
    4. // this.name = name
    5. // }
    6. static sayHi() {
    7. console.log('hi');
    8. }
    9. }
    10. const a5 = new A()
    11. console.log(A.name1);
    12. A.sayHi()
    13. // console.log(a5.name1); 报错
    14. // a5.sayHi() 报错

    public、private、protected修饰符

    public修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的

    1. class B {
    2. public name1: string // 公有的属性
    3. public constructor(name: string) { // 公有的方法
    4. this.name1 = name
    5. }
    6. public p() {
    7. console.log(this.name1);
    8. }
    9. }
    10. const aa = new B('张三')
    11. console.log(aa.name1);
    12. aa.p()

    private 修饰的属性或方法是私有的,不能在声明它的类的外部访问。包括其子类。但是这个属性和方法是可以被继承的

    私有属性的属性和方法可以被继承,但是在子类中无法访问私有属性

    protected修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

    外部无法访问,但子类中可以访问到

    readonly以及参数属性

    readonly是只读属性,但是在构造函数是可以修改的

    readonly以及三个修饰符(public、private、protected)定义在参数上,那就是创建并且初始化age参数

    1. class X {
    2. // readonly age: number // 只读属性,但是在构造函数是可以修改的
    3. // readonly以及三个修饰符定义在参数上,那就是创建并且初始化age参数
    4. // constructor(readonly age: number) {
    5. // constructor(public age: number) {
    6. // constructor(private age: number) {
    7. constructor(protected age: number) {
    8. // this.age = age
    9. }
    10. update() {
    11. // this.age = 15 报错,不能被修改,只读属性
    12. }
    13. }
    14. const xx = new X(13)
    15. console.log(xx);
    16. // xx.age = 12 报错,不能被修改,只读属性

    抽象类

    abstract定义一个抽象类,为子类服务

    抽象类不允许被实例化,可以在子类中具体实现抽象类中的抽象方法

    1. abstract class Y { // abstract定义一个抽象类
    2. abstract name: string // 抽象属性
    3. // constructor(name){
    4. // this.name=name
    5. // }
    6. abstract sayHi() // 不能有具体实现
    7. }
    8. // 不能被实例化
    9. class Z extends Y {
    10. name: string
    11. constructor(name) {
    12. super()
    13. this.name = name
    14. }
    15. // 子类中具体实现抽象类中的抽象方法
    16. sayHi() {
    17. console.log('hi');
    18. }
    19. }
    20. const z = new Z('张三')
    21. console.log(z.name);
    22. z.sayHi()

    类的类型

    类可以作为类型给变量定义类型

    1. class Car {
    2. name: string
    3. constructor(name: string) {
    4. this.name = name
    5. }
    6. }
    7. class Ben extends Car {
    8. constructor(name) {
    9. super(name)
    10. }
    11. }
    12. const car: Car = new Car('bm')
    13. const ben: Ben = new Ben('')

    类实现接口

    实现(implements)是面向对象中的一个重要概念

    举例来说,人会唱歌跳舞,动物也会唱歌跳舞,我们就可以把唱歌跳舞提取出来作为一个接口,让人和动物去实现它:

    1. interface ISing {
    2. // 这个方法是没有任何的实现
    3. sing()
    4. }
    5. interface IDance {
    6. dance()
    7. }
    8. class P implements ISing, IDance { // 人:唱歌、跳舞
    9. sing() {
    10. console.log('sing');
    11. }
    12. dance() {
    13. console.log('dance');
    14. }
    15. }
    16. class Ani implements ISing, IDance { // 动物:唱歌、跳舞
    17. sing() {
    18. console.log('sing');
    19. }
    20. dance() {
    21. console.log('dance');
    22. }
    23. }
    24. const p1 = new P()
    25. const an = new Ani()
    26. p1.sing()
    27. p1.dance()
    28. an.sing()
    29. an.dance()

    声明合并

    接口中的属性在合并时会简单的合并到一个接口中,相当于取并集

    函数合并--->函数重载

    合并的属性的类型必须是唯一的

    类的合并与接口合并是一样的

    1. interface Cat {
    2. name: '大橘',
    3. gender: '女'
    4. }
    5. interface Cat {
    6. name: '大橘',
    7. age: 1
    8. }
    9. const cat: Cat = { name: '大橘', age: 1, gender: '女' }

    15、泛型

    泛型的基本使用

    使用泛型,在定义时不需要先确定类型,而是使用的时候再去确定

    如果没有确定的话,就会走类型推断

    原则上不推荐使用any,用T表示任意输入的类型

    例如:

    1. // 需求:定义一个函数,传入两个参数,第一个参数是数据,第二个参数是数量
    2. // 函数的作用:根据熟练产生对应个数的数据,存放在一个数组中
    3. // (123,3)--->[123,123,123]
    4. function getArr(value: T, count: number): T[] {
    5. const arr: T[] = []
    6. for (let i = 0; i < count; i++) {
    7. arr.push(value)
    8. }
    9. return arr
    10. }
    11. console.log(getArr(123, 3));
    12. console.log(getArr('你好', 3));

    多个泛型参数的函数

    定义泛型的时候,可以一次定义多个类型参数

    1. // [123,'123']--->['123',123]
    2. function updateArr(t: [T, U]): [U, T] {
    3. return [t[1], t[0]]
    4. }
    5. console.log(updateArr(['123', 123])); // [ 123, '123' ]
    6. console.log(updateArr([true, 123])); // [ 123, true ]

    泛型约束

    泛型约束,约束这个任意输入的类型,必须要有length属性

    例如:获取一个参数的长度

    1. interface ILength {
    2. length: number
    3. }
    4. function getLength1extends ILength>(x: T): number {
    5. return x.length
    6. }
    7. // console.log(getLength1(123)); // 报错number类型没有length属性
    8. console.log(getLength('123'));

    泛型接口和泛型类

  • 相关阅读:
    普通人做自媒体怎么赚钱?
    【clickhouse专栏】clickhouse性能为何如此卓越
    LED驱动器 DC恒流电源板模块
    Bash基本功能—输入输出重定向
    Python 数据可视化:Seaborn 库的使用
    Spring的前置增强,后置增强,异常抛出增强、自定义增强
    酷开系统更多惊喜,尽享畅快观影之旅
    【C++】类的封装 ④ ( 访问控制权限 | struct 和 class 关键字定义类的区别 | 类的默认访问权限 | 类的默认继承方式 )
    DOM对象和jquery对象
    论文的三种状态
  • 原文地址:https://blog.csdn.net/qq_45256497/article/details/133167936