完整地讲一下Typescript

前言

  Typescript作为ECMA的实现,javascript的超集,目前已经广泛在项目中使用。typescript是什么?有什么具体功能?这些已经被大家写得差不多了。在这里,我不再赘述ts的作用,而是直接用起来,从一个初学者角度告诉大家一些使用typescript的心得。下文将会完整地讲解一下typescript各个方面的具体用法,力求在我总结之余让大家有所收获。

正文

在使用之前先总结几点可以帮助理解的要点:

  • ts可以由tsc(Type Script Complier)编译器编译成js,项目的ts代码无论在开发时还是打包后都会经历编译环节,最终执行的只会是js代码。
  • ts是js的超集,支持所有的JavaScript语法,支持es6、es7等新语法,不需要使用babel进行转换,在tsconfig.json配置文件中进行配置之后,tsc便能将其编译成指定版本的js代码。
  • ts可以通过tsconfig.json配置一些编译规则,违反这些规则是导致编译错误,但是即便编译错误不会打断编译,tsc还是会继续完成编译。

开始使用

  1. 全局安装typescript

    yarn global add typescript
    // 或使用 npm
    npm i typescript -g
    
  2. 使用tsc进行编译

    // 使用默认的配置编译helloword.ts文件
    tsc helloword.ts 
    
  3. 使用tsconfig.json配置文件

    // 在根目录下建立tsconfig.json配置文件
    {
        // 编译选项
        "compilerOptions": {
            // 编译目标,如'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
            "target": "es5",
            // 编译代码使用的模块 'commonjs', 'amd', 'system', 'umd' or 'es2015'
            "module": "commonjs",
            // 输出文件夹,默认会对应ts文件下生成同名js文件
            "outDir": "./dist",
            // 类型声明文件的目录,工作目录下@types文件会自动加入
            "typeRoots": [],
        },
        // 进行编译的文件
        // 包含在files中的文件是一定会进行编译(即使使用exclude去除)
        "files": [
            "hello.ts",
            "word.ts"
        ],
        // 要编译的目录或文件
        "include": [
            "./folder"
        ],
        // 不要包含的目录或文件
        "exclude": [
            "./folder/**/*.spec.ts",
            "./folder/someSubFolder"
        ]
    }
    

    完整的配置选项可以参考 typescript官网

    在建立好配置文件之后,直接执行tsc,编译好的js文件便会存在于js目录,当module为commonjs时,可以直接使用node进行执行测试。当然还可以使用自动编译,在tsconfig.json顶层中加入 “compileOnSave”: true,告诉IDE保存后进行编译,vscode按照typescript插件,之后执行 tsc -w,这样子之后就能进行自动编译。

定义类型

  typescript是type+script(js)。它的本质是通过类型定义来限制js灵活多变的语法。ts提供了一些基本类型,但同时允许开发者自定义类型,在一些复杂情况下还可以使用一些高级类型。

基本类型

  ts提供了Boolean、Number、String、Array、Tuple、Enum、Any、Void、Null、Undefined、Never、Object 共12种基本类型。

  1. Boolean、Number、String

     // 大部分类型的使用非常简单
    let bool: boolean = true;
    let num: number = 1213;
    let str: string = "Hello World";
    
  2. Array和Tuple(元组)

    // 数组类型
    let arr: number[] = [1213,2324]
    // 或者 
    const arr2: Array<string> = ['1213', '234234']
    // 元组为有限个有序的数组,元组需要对数组的每个元素声明类型
    let tup: [string, number] = ["121", 2321];
    tup[0] = "wadsas";
    tup[0] = 1212 // 报错
    
  3. Enum类型

      枚举类型是一种很特殊的类型,其它的类型声明在编译成js代码之后便不会存在,但枚举类型是会编辑成js代码的。

    enum Tristate {
      False,
      True,
      Unknown
    }
    // 编译成js之后
    var Tristate;
    (function(Tristate) {
      Tristate[(Tristate['False'] = 0)] = 'False';
      Tristate[(Tristate['True'] = 1)] = 'True';
      Tristate[(Tristate['Unknown'] = 2)] = 'Unknown';
    })(Tristate || (Tristate = {}));
    // 也就是以下对象
    {0: "False", 1: "True", 2: "Unknown", False: 0, True: 1, Unknown: 2}
    let tri: Tristate = Tristate.False
    

    枚举选项的值默认是从0开始,上面的Tristate中False为0, True为1,Unknown为2,我们可以改变枚举的值:

    enum HighColor {
      Green,
      Black = 5,
      Blue
    }
    // Green为0,Black为5,Blue为6
    // 字符串枚举
    enum Type {
      ON_LINE = "ON_LINE",
      DOWN = "DOWN",
      OTHER = "OTHER"
    }
    

    还可以使用 enum + namespace 的声明的方式向枚举类型添加静态方法

    enum PersonType {
      young,
      middle,
      old
    }
    namespace PersonType {
      export function isOld(person: PersonType) {
        return person === PersonType.old;
      }
    }
    const Marry: PersonType = PersonType.old;
    console.log(PersonType.isOld(Marry));
    
  4. Any和Object

    Any是任意类型,当一个变量被声明为了any类型,它可以是任何值,就如js一样可以随意改变其值而不会有提示,当从js项目迁移到ts,any可以提供极大的便利,但一个项目内应该尽量少地使用any类型,因为这意味着你放弃类型检查。

    let a: any = 1231;
    a = "12313";
    a = true
    

    Object是对象类型,它仅表示变量是对象类型,不会对对象的属性做出限制,一个比较适合的场景是Object.create(o: object)

    declare function create(o: object | null): void;
    create({ prop: 0 }); // OK
    create(null); // OK
    create(42); // Error
    let obj: object = {a: 12}
    obj = {b: 12, c: 88}
    obj.d = 1212 // 报错
    
  5. Void、Never、Null和Undefined

    Void一般用以表示函数或方法没有返回值,Never代表永远不会发生的类型。

    function log(name: string):void {
        console.log(name)
    }
    // 抛出了错误,程序永远没有返回值
    function error(message: string): never {
        throw new Error(message);
    }
    // 函数内有一个死循环,永远不会执行到循环外的代码
    function infiniteLoop(): never {
        while (true) {
        }
    }
    

    Null和Undefined类型为其它所有类型的子类型,这意味着该类型可以赋值为其它任何类型,但这必须在strictNullChecks编译选项为false的情况下。

    let n: null = null
    let u: undefined = undefined;
    let str: string = '1212'
    str = n
    

自定义类型

  1. 内联方式
  2. interface和type
  3. 字面量类型

https://juejin.im/post/5e3408e851882526185252c1

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论