CodeLife

vuePress-theme-reco yuqing521    2019 - 2021
CodeLife CodeLife

Choose mode

  • dark
  • auto
  • light
主页
分类
  • 日常
  • 后端
  • 基础知识
  • 前端
  • 读书
标签
时间轴
文档
  • vuepress-reco
Github
联系我
  • 关于我
  • CSDN
  • 掘金
author-avatar

yuqing521

27

文章

33

标签

主页
分类
  • 日常
  • 后端
  • 基础知识
  • 前端
  • 读书
标签
时间轴
文档
  • vuepress-reco
Github
联系我
  • 关于我
  • CSDN
  • 掘金
  • TypeScript 笔记

    • 类型注解
      • 有哪些基础类型注解?
      • 什么是类型注解和类型推断、类型断言?
      • 对象的类型
      • 函数的类型注解
      • 数组的类型注解
    • 元组
      • 接口
        • ES6 class类中应用TS
          • class类的修饰器
          • class类的构造函数中使用类型校验
          • class类的getter、setter和static
          • class类的只读属性
          • 抽象类
        • 联合类型和类型保护
          • 枚举
            • 泛型
              • 函数中的泛型使用
              • class类中使用泛型
            • 配置文件tsconfig.json

            TypeScript 笔记

            vuePress-theme-reco yuqing521    2019 - 2021

            TypeScript 笔记


            yuqing521 2020-12-26 TypeScript

            image.png

            # TypeScript 笔记

            TypeScript 的类型校验是给程序员看的,在编译后不会存在TS代码。

            # 类型注解

            function fn(person: string):void{ // 参数类型是字符串,没有返回值
                ///...
            }
            fn('str') // 如传递参数非字符串,vscode编辑器中或在编译时将给出错误提示
            
            const test:number = 1
            
            
            1
            2
            3
            4
            5
            6
            7

            # 有哪些基础类型注解?

            // 基础类型
            :string
            :number
            :boolean
            
            :null  // 只能是null值
            :undefined // 只能是undefined值
            
            :symbol
            
            // 引用类型
            :object // 不常用,多使用接口来给对象进行类型注解
            
            // 其他
            :any  // 任意类型
            :void  // 空,用于函数的无返回值的注解
            :never // 用于标注函数代码永远执行不完(如抛出错误的函数,死循环函数)
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18

            # 什么是类型注解和类型推断、类型断言?

            类型注解 是显式的标注类型

            类型推断 是编辑器根据值来自动推断出类型 (编辑器中鼠标移到变量会显示类型的提示)。

            类型断言 是告诉编译器,“相信我,它就是这个类型”。

            // 类型注解就是显式的写出类型
            const myNumber: number = 123
            
            // 类型推断是根据值来推断类型 (鼠标移到变量会显示类型(或直接显示值)的提示)
            const myString = 'test'
            
            // 类型断言(开发者明确知道是什么类型)
            const someValue:any = 'abc'
            const strLength:number = (someValue as string).length // 断言someValue是字符串类型
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10

            # 对象的类型

            // 对象字面量的类型检查
            const xiaojiejie: {
              name: string,
              age: number
            } = {
              name: '小红',
              age: 18
            }
            
            // 标注:object
            const obj:object = {}
            
            // 使用接口
            interface Person{
                name: string
                age: number
            }
            const xjj: Person = {
                name: 'xh',
                age: 18
            }
            
            // class类的类型检查
            class Parson { }
            const xiaobai: Parson = new Parson()
            
            // 函数和返回值的类型检查
            const fn: ()=> string = () => '123'
            
            
            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

            # 函数的类型注解

            // 函数返回值的类型注解 fn(): number {}
            function getTotal2(one: number, two: number): number {
              return one + two
            }
            getTotal2(1,2)
            
            // 无返回值: void
            function sayHello(): void {
              console.log("Hello")
            }
            
            // 永远执行不玩的函数
            function setTimer():never {
              throw new Error()
              console.log(123)
            }
            
            // 参数是对象时的注解 (也可以用接口)
            function add({ one, two }: {one: number, two: number}) {
              return  one + two
            }
            
            const total = add({one: 1, two: 2})
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24

            # 数组的类型注解

            const numberArr: number[] = [1, 2, 3]
            const stringArr: string[] = ['a', 'b']
            const undefinedArr: undefined[] = [undefined, undefined]
            const arr: (number | string | boolean)[] = [1, 'a', true, false] // 用到联合类型
            
            // 类型别名 type alias
            type lady = { name: string, age: number }
            
            const xiaojj: lady[] = [
              {
                name: 'xiaojj',
                age: 90
              },
              {
                name: 'j',
                age: 30
              }
            ]
            
            // 或用类的方式
            class Ady2 {
              name: string;
              age: number;
            }
            
            const xiaojj2: Ady2[] = [
              {
                name: 'xiaojj',
                age: 90
              },
              {
                name: 'j',
                age: 30
              }
            ]
            
            
            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

            # 元组

            元组,可以理解为:已知元素数量和类型的数组

            // 联合类型
            const xjj:(string | number)[] = ['a',22,'b'] // 规定整个数组当中可以有string或number
            
            // 元组注解 注意这里的注解只有一个中括号
            const xjj1: [string, number, number] = ['a', 22, 33] // 规定了数组每个元素对应位置的类型
            
            // Note: 在开发中元祖的使用在相对少
            
            // CSV的方式定义数据格式; (二维数组时需要多加一个中括号)
            const xjj2: [string, number, number][] = [
              ['a', 22, 33],
              ['a', 22, 33]
            ]
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14

            # 接口

            接口,可以理解为对象属性的类型描述。和类型别名类似,不同的是 接口必须是一个对象,而别名可以直接是一个类型,如type Girl = string

            interface Girl { // 接口 (理解:对象属性的类型描述)
              readonly name: string; // 只读属性 (定义之后不能再修改)
              age: number;
              waistline?: number; // 加个问号表示是可选值
              [propname: string]: any; // 表示可以有不限制属性名的属性,但属性名需要是字符串,值可以是任意类型
              say(): string; // 函数类型,返回值是string (如无返回值时是 void)。  say()也可以加入参数类型检查,如say(p:number)
            }
            // 和类型别名类似,不同的是 接口必须是一个对象,而别名可以直接是一个类型,如 type Girl = string
            
            // 接口的继承
            interface Teacher extends Girl {
              teach(): string;
            }
            
            const girl = {
              name: '大脚',
              age: 18,
              sex: '女',
              say() {
                return '欢迎光临'
              },
              teach() {
                return '教'
              }
            }
            
            const screenResume = ({ name, age, bust, sex }: Girl) => {
              console.log(name, age, bust, sex)
            }
            const getResume = ({ name, age, bust, teach}: Teacher) => {
              teach();
              console.log(name, age, bust)
            }
            screenResume(girl)
            getResume(girl)
            
            // 接口在class类中的使用
            class xiaojjj implements Girl {
              name = "xiaojj"
              age = 18
              bust = 98
              sex = '女'
              say() {
                return '欢迎光临'
              }
            }
            
            
            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

            可索引的类型

            interface Arr {
                [index: number]:string   // 表示通过索引访问数据时返回的类型是string
            }
            
            const myArr:Arr = ['1','2','3']
            const myStr:string = myArr[1]
            
            
            1
            2
            3
            4
            5
            6
            7

            # ES6 class类中应用TS

            # class类的修饰器

            // 类的修饰器:
            // public (公共) 允许内外部使用
            // protected (受保护的) 允许在内部和继承内使用
            // private (私有) 允许在内部使用,但不能在继承中使用
            
            // 类的内部和外部,{}内属于内部,外面是外部
            class Person {
               // public 内外都可以使用,可省略,不写时默认public。 protected只允许内部使用
              name: string // 这里的string注释是TS使用的
              private age: 18
              public sayHello() {
                console.log(this.name + this.age + 'say hello')
              }
            }
            
            class Teacher2 extends Person {
              public sayBye() {
                console.log(this.name + ' say bye') // protected 可以在继承中使用到
              }
            }
            
            const person = new Person();
            person.name = 'test' // 在类的外部定义
            console.log(person.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

            # class类的构造函数中使用类型校验

            class Person2 {
              constructor(public name: string) {
                this.name = name
              }
            }
            
            class Teacher3 extends Person2{
              constructor(public age: number) {
                super('test-name') // 这里传的值是给Person2的构造函数。即使父类没有构造函数,子类的构造函数内也要写super()
              }
            }
            const teacher3 = new Teacher3(18)
            console.log(teacher3.name)
            console.log(teacher3.age)
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15

            # class类的getter、setter和static

            class Xjj {
              constructor(private _age: number) { }
              get age() {
                return this._age - 10;
              }  // 访问器属性,以属性的形式访问age,并可以对属性进行包装
              set age(age: number) {
                this._age = age+3;
               }
            }
            
            const dj = new Xjj(28);
            dj.age = 25
            
            console.log(dj.age)
            
            // 静态属性 static。  静态属性指不需要通过实例化,直接通过Girl.prop的方式就可以访问到属性
            class Girl {
              static sayLove() {
                return 'I love you'
              }
            }
            
            // const girl = new Girl()
            console.log(Girl.sayLove())
            
            
            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

            # class类的只读属性

            // 只读属性
            class Person {
              public readonly _name: string // 只读属性
              constructor(name: string) {
                this._name = name;
              }
            }
            
            const person = new Person('testName');
            // person._name = '222'; // 不能修改只读属性
            console.log(person._name)
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12

            # 抽象类

            / 抽象类
            abstract class Girls {
              abstract skill(); // 注意这里只是定义抽象方法,而不具有方法的实现
            }
            
            class Waiter extends Girls{ // 继承了抽象类之后要 实现抽象类内的成员
              skill() {
                console.log('大爷1')
              }
            }
            
            class BaseTeacher extends Girls{
              skill() {
                console.log('大爷2')
              }
            }
            
            class SeniorTeacher extends Girls{
              skill() {
                console.log('大爷3')
              }
            }
            
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23

            # 联合类型和类型保护

            联合类型 指某个参数可以是多种类型。

            类型保护 指参数属于某个类型才有相应的操作。

            interface Waiter {
              anjiao: boolean
              say: () => {}
            }
            
            interface Teacher {
              anjiao: boolean
              skill: () => {}
            }
            
            function judgeWho(animal: (Waiter | Teacher)) { // 联合类型
              // 第一种断言方法
              if (animal.anjiao) {
                // (animal as Teacher) 的意思是:断言 animal 是 Teacher类型
                (animal as Teacher).skill()
              } else {
                (animal as Waiter).say()
              }
            
              // 第二种断言方法
              if ('skill' in animal) {
                animal.skill()
              } else {
                animal.say()
              }
            
              // 第三种类型保护方法是使用typeof来判断 (代码省略)
            }
            
            class NumberObj {
              count: number
            }
            function addObj(first: object | NumberObj, second: object | NumberObj) { // 联合类型
              if (first instanceof NumberObj && second instanceof NumberObj) { // 类型保护
                return first.count + second.count;
              }
              return 0;
            }
            
            
            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

            # 枚举

            // Enum枚举类型   (个人理解枚举:约定一组可选的常量。 使用常量名表示某个值的含义,增强可读性。)
            
            // js写法
            // const Status = {
            //   MASSAGE: 0,
            //   SPA: 1,
            //   DABAOJIAN: 2
            // }
            
            // ts写法
            enum Status {
              MASSAGE,  // 如果想从1开始,给MASSAGE = 1, 即可
              SPA,
              DABAOJIAN
            } // 默认赋值 0 、1、2
            
            console.log(Status.MASSAGE, Status[0]) // 0, MASSAGE  可以通过下标反查
            
            function getStatus(status: any) {
              if (status === Status.MASSAGE) {
                return 'massage'
              } else if (status === Status.SPA) {
                return 'spa'
              } else if (status === Status.DABAOJIAN) {
                return 'dabaojian'
              }
            }
            
            const result = getStatus(Status.SPA)
            console.log(result)
            
            
            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

            # 泛型

            泛型,最简单的理解:泛指的类型。(类似函数中的形参与实参)

            # 函数中的泛型使用

            // function join(first: string | number, second: string | number) {
            //   return `${first}${second}`
            // }
            // join('jspang', 1); // 如果我想第一个参数是字符串,第二个也必须是字符串,这么就用到泛型
            
            // 泛型使用,如同定义形参,在调用时指定类型
            function join<JSPang>(first: JSPang, second: JSPang) {
              return `${first}${second}`}
            
            join<string>('jspang', '123');
            join<number>(11, 22);
            
            // 泛型中数组的使用
            function myFun<ANY>(params:ANY[]) { // ANY[] or Array<ANY>
              return params
            }
            myFun<string>(['a', 'b'])
            
            // 两个类型参数的使用(工作中,常用T表示泛型)
            function join2<T,P>(first: T, second: P) {
              return `${first}${second}`}
            
            join2<string,number>('jspang', 123);
            join2<number, string>(11, '22');
            join2(11, '22'); // 泛型也支持类型推断 (鼠标移到函数名有提示)
            
            
            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

            # class类中使用泛型

            // class SelectGirl {
            //   constructor(private girls: string[] | number[]) { } // private 私有的参数,外部无法修改
            //   getGirl(index: number): string | number {
            //     return this.girls[index]
            //   }
            // }
            
            // 使用泛型
            class SelectGirl<T> {   // 泛型的约束: <T extends number | string>
              constructor(private girls: T[]) { } // private 私有的参数,外部无法修改
              getGirl(index: number): T {
                return this.girls[index]
              }
            }
            
            // const selectGirl = new SelectGirl<string>(['大脚', 'xiaohong', 'xiaobai'])
            const selectGirl = new SelectGirl<number>([101, 102, 103])
            console.log(selectGirl.getGirl(1))
            
            // 泛型中的继承
            interface Girl {
              name: string
            }
            class SelectGirl2<T extends Girl> { // 泛型T中必须有一个name属性,继承自Girl接口
              constructor(private girls: T[]) { } // private 私有的参数,外部无法修改
              getGirl(index: number): string {
                return this.girls[index].name
              }
            }
            
            const selectGirl2 = new SelectGirl2([
              {name: '大脚1'},
              {name: '大脚2'},
              {name: '大脚3'}
            ])
            
            console.log(selectGirl2.getGirl(1))
            
            
            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

            # 配置文件tsconfig.json

            // 此文件由命令 tsc -init 生成
            // 直接运行 tsc 命令就会运用此配置文件
            // 选项详解:https://www.tslang.cn/docs/handbook/compiler-options.html
            {
              // "include": ["demo15-1.ts"],              // 要编译的指定文件,不配置此项时运行tsc默认编译全部
              // "files": ["demo15-1.ts"],                // 和include类似
              // "exclude": ["demo15-3.ts"],              // 要排除编译的指定文件
              "compilerOptions": { // 编译选项
                /* 基本选项 */
                // "incremental": true,                   /* 启用增量编译 */
                "target": "es5",                          /* 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
                "module": "commonjs",                     /* 指定模块代码生成: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
                // "lib": [],                             /* 指定要包含在编译中的库文件. */
                // "allowJs": true,                       /* 允许编译javascript文件*/
                // "checkJs": true,                       /* 报告.js文件中的错误。 */
                // "jsx": "preserve",                     /* 指定 JSX代码生成: 'preserve', 'react-native', or 'react'. */
                // "declaration": true,                   /* 生成相应的 .d.ts文件 */
                // "declarationMap": true,                /* 为每个相应的 .d.ts文件生成一个sourcemap (编译后代码对源码的映射)*/
                "sourceMap": true,                        /* 生成源文件与输出文件的映射关系文件(.map)。*/
                // "outFile": "./",                       /* 将输出文件合并为一个文件. */
                "outDir": "./build",                      /* 输出的js文件目录。 */
                "rootDir": "./src",                       /* ts源文件目录。 */
                // "composite": true,                     /* 启用 项目编译 */
                // "tsBuildInfoFile": "./",               /* 指定用于存储增量编译信息的文件 */
                // "removeComments": true,                /* 不输出注释到编译结果.(删除所有注释,除了以 /!*开头的版权信息。) */
                // "noEmit": true,                        /* 不发出输出.Do not emit outputs. */
                // "importHelpers": true,                 /* 从“tslib”导入发出助手. Import emit helpers from 'tslib'. */
                // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
                // "isolatedModules": true,               /* 将每个文件作为单独的模块(与“ts.transpileModule”类似) */
            
                /* 严格的类型检查选项 */
                "strict": true,                           /* 启用所有严格类型检查选项。 打开此选项后,下面这些选项就不需要单独设置*/
                // "noImplicitAny": true,                 /* 对隐含的“any”类型的表达式和声明引发错误. (为false时允许any不用特意声明)*/
                // "strictNullChecks": true,              /* 启用严格的null检查. (为false时允许赋值为null)*/
                // "strictFunctionTypes": true,           /* 启用严格检查函数类型. */
                // "strictBindCallApply": true,           /* 启用函数上严格的“bind”、“call”和“apply”方法. */
                // "strictPropertyInitialization": true,  /* 启用 严格检查类中的属性初始化. */
                // "noImplicitThis": true,                /* 在隐含的“any”类型的“this”表达式上引发错误。 */
                // "alwaysStrict": true,                  /* 以严格模式解析并为每个源文件发出“use strict”。 */
            
                /* 附加检查。Additional Checks  */
                // "noUnusedLocals": true,                /* 若有未使用的局部变量则抛错 */
                // "noUnusedParameters": true,            /* 若有未使用的参数则抛错。 */
                // "noImplicitReturns": true,             /* 不是函数的所有返回路径都有返回值时报错。*/
                // "noFallthroughCasesInSwitch": true,    /* 报告switch语句的fallthrough错误。(即,不允许switch的case语句贯穿) */
            
                /* 模块解析选项 */
                // "moduleResolution": "node",            /* 决定如何处理模块:'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
                // "baseUrl": "./",                       /* 用于解析非绝对模块名称的基础目录。 */
                // "paths": {},                           /* 模块名到基于 baseUrl的路径映射的列表。 */
                // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
                // "typeRoots": [],                       /* List of folders to include type definitions from. */
                // "types": [],                           /* 要包含的类型声明文件名列表 */
                // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
                "esModuleInterop": true                   /* 启用s emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
                // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
                // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
            
                /* Source Map Options */
                // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
                // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
                // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
                // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
            
                /* Experimental Options */
                // "experimentalDecorators": true,        /* 启用s experimental support for ES7 decorators. */
                // "emitDecoratorMetadata": true,         /* 启用s experimental support for emitting type metadata for decorators. */
              }
            }
            
            
            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