• Typescript项目注意点和基本类型介绍


    从typescript源文件到执行的过程

    执行者 步骤 说明
    TSC 1. TypeScript Source -> TypeScript AST TSC将ts文件转为TS AST(abstract syntax tree)
    TSC 2. AST is checked by typechecker TSC的类型检查器对AST做类型检查
    TSC 3. TypeScript AST -> Javascript Source TSC将TS AST转为JS的源代码(可能是ES3/5/6)
    JS(浏览器/Node.js) 4. Javascript Source -> Javascript AST JS运行时将JS源码转为JS AST
    JS(浏览器/Node.js) 5. Javascript AST -> bytecode JS运行时将JS AST 转为字节码,准备运行
    JS(浏览器/Node.js) 6. Bytecode is evaluated by runtime JS运行时运行js字节码

    其中1-3步是TSC处理的,4-6步为JS运行时处理,可能是浏览器也可能是Node.js。

    从上面步骤可以知道,TSC做类型检查是在将TS AST转为JS源码之前,也就是说从TS AST转为JS源码时,是没有做类型检查的。检查类型时针对TS AST的,即第二步。

    也意味着TS的类型系统,强类型的各种机制,仅仅对类型检查有用,对产出的JS无影响,增加类型不会污染JS源文件。

    关于tsconfig.json

    可以通过 tsc –init 创建tsconfig.json文件,如下:

    {
      "compilerOptions": {
        "target": "es2015",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
        "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
        "lib": ["es2015"],                             /* Specify library files to be included in the compilation. */
        "sourceMap": true,                     /* Generates corresponding '.map' file. */
        // "outFile": "./",                       /* Concatenate and emit output to single file. */
        "outDir": "dist",                        /* Redirect output structure to the directory. */
        "strict": true,                           /* Enable all strict type-checking options. */
        "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
        "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
        "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
      }
    }
    

    下面主要看几个常用配置:

    配置属性 描述
    include 告诉TSC在哪里找到ts文件
    lib 告诉TSC当前运行时已存在的API,通常包括:ES5的bind,新增数组方法,ES6的新增方法等
    module 告诉TSC将ts文件转为那种模块标准的js文件,通常有cmj,cmd,es6等
    outDir 告诉TSC将转换后的文件放到哪个目录
    strict 告诉TSC是否进行严格的类型检查
    target 告诉TSC将ts转换成哪个版本的js,通常有ES3,ES5,ES6等
    noImplicitAny 是否允许存在未定义的类型,即隐式类型。TSC不会自己猜测类型
    alwaysStrict TSC会在产出的每个js文件中带上use strict语句

    关于tslint

    可以通过 tslint –init 创建默认的tslint.json文件,如下:

    {
        "defaultSeverity": "error",
        "extends": [
            "tslint:recommended"
        ],
        "jsRules": {},
        "rules": {},
        "rulesDirectory": []
    }
    

    {}类型

    当将一个变量设置为{}类型是,意味着此变量的值可以是除了null和undefined之外的任何值。

    let a:{} = 1;
    let b:{} = Symbol('b');
    let c:{} = null; // Type 'null' is not assignable to type '{}'.
    let d:{} = undefined; // Type 'undefined' is not assignable to type '{}'.
    

    object类型

    当将一个变量设置为object类型时,意味着此变量的值可以是除了字符串,数字,Symbol,null,undefined,布尔值之外的任何值。

    let a:object = new Date();
    let b:object = function(){};
    let c:object = [];
    let d:object = new RegExp('');
    let e:object = true; // Type 'true' is not assignable to type 'object'.
    let f:object = Symbol(); // Type 'symbol' is not assignable to type 'object'.
    let g:object = 1; // Type '1' is not assignable to type 'object'.
    let h:object = '1'; // Type '"1"' is not assignable to type 'object'.
    

    Object类型

    同{}类型。

    Value {} object Object
    {} Yes Yes Yes
    [‘a’] Yes Yes Yes
    function(){} Yes Yes Yes
    new String(‘a’) Yes Yes Yes
    ‘a’ Yes No Yes
    1 Yes No Yes
    Symbol() Yes No Yes
    true Yes No Yes
    null No No No
    undefined No No No

    []类型

    当一个变量声明为[]类型时,表示变量的值必须为空数组。如果隐式声明为[],则表示元素的类型为any,即任意类型的值。如:

    let a:[] = [];
    a = [1]; // Type '[number]' is not assignable to type '[]'.
    let b = []; // 隐式声明b为数组,元素类型是any类型
    b.push(1);
    b.push(null);
    

    Tuples类型

    此类型是array的子类型,继承自array类型。Tuples类型的数组必须显式申明其元素的类型,且数组长度不可变。如:

    // 声明定长的数组
    let arr: [string,number,boolean] = ['a',2,true];
    
    // 二维数组的声明
    // 分步解释:
    // let data: number[] 表示声明一个元素为数字的数组
    // let data: [][] 表示声明一个元素为空数组的数组
    // let data: [number, number][] 表示声明一个元素为两个元素的tuples类型的数组,且tuples的两个元素必须都为number类型
    // let data: [number, number?][] 表示数组的第二个元素可选
    let data: [number, number?][] = [[1,2],[3],[4,5]];
    
    // 声明不定长数组,且指定第一个元素的类型,其他元素类型任意
    let data1: [string,...any[]] = ['11','s',32];
    

    枚举类型

    枚举类型主要处理两类事务:定义字符串到数字的映射或字符串到字符串的映射。TS会自动将枚举类型的每个成员映射到一个数字,默认是从0开始,也可是是显式定义数字,开始位置自己决定,如:

    // 默认从0开始
    enum lang {Chinese, English, Russian}; 
    let a = lang.Chinese;
    console.log(a, lang.English, lang.Russian); // 0, 1, 2
    // 定义从3开始
    enum lang {Chinese=3, English, Russian}; 
    let a = lang.Chinese;
    console.log(a, lang.English, lang.Russian); // 3, 4, 5
    // 自定义或者自动赋值
    enum lang {Chinese=3, English=6, Russian}; 
    let a = lang.Chinese;
    console.log(a, lang.English, lang.Russian); // 3, 6, 7
    

    看枚举类型被TS转换后的形式,如:

    var lang;
    (function (lang) {
        lang[lang["Chinese"] = 3] = "Chinese";
        lang[lang["English"] = 9] = "English";
        lang[lang["Russian"] = 10] = "Russian";
    })(lang || (lang = {}));
    ;
    

    我们可以通过数字访问到字符串,通过字符串访问到数字,如:

    console.log(lang['English'], lang[lang.English]); // 9 English
    

    readonly修饰符

    声明对象的某个属性为readonly

    let a: {a:string, readonly b:number} = {a:'2', b:3};
    a.b = 4; // Cannot assign to 'b' because it is a read-only property.
    

    声明数组为只读

    let as: readonly number[] = [1,2,3];
    as.push(2); // Property 'push' does not exist on type 'readonly number[]'.
    as.concat(3); // concat函数不会对原数组修改,而是返回新的数组,所以此处合法。
    
    // 还可以这样声明
    let arr: ReadonlyArray<string> = ['2'];
    arr.push('3'); // Property 'push' does not exist on type 'readonly string[]'.
    // 或者
    let arr: Readonly<string[]> = ['22'];
    

    声明类的属性为只读。类的只读属性可以在声明的时候赋值,或者构造函数中赋值,其他地方都不允许赋值。如:

    class Foo{
        readonly bar = 1;
        readonly baz:string;
        constructor(){
            this.baz = 'hello';
        }
        setBaz(value:string){
            this.baz = value; // Cannot assign to 'baz' because it is a read-only property.
        }
    }
    console.log(new Foo().baz);
    

    类型的组合

    有时候某个变量的值可能需要取其他类型中的某一个类型,这时可以给此变量的类型设置为这些类型的并集,如:

    let prop: string|number = 3;
    prop = '3'; // 可以被赋值,因为prop可以为string和number类型中的一个
    
    // 数组里可以是字符串也可以是数字
    type StringOrNumber = string|number;
    let a: StringOrNumber[] = []; // 或者直接这样:let a: (string|number)[] = [];
    a.push(1);
    a.push('a');
    a.push(true); // 类型错误,不可以有布尔类型
    
    type Cat = {name:string, purrs:boolean};
    type Dog = {name:string, barks:boolean, wags:boolean}
    type CatOrDogOrBoth = Cat|Dog;
    let cat: CatOrDogOrBoth = {name: 'John', purrs: true};
    // 类型错误 {name: 'John', barks: false} 不属于Cat和Dog中的任何一个类型
    let cat2: CatOrDogOrBoth = {name: 'John', barks: false}; 
    // 类型错误,同上
    let cat3: CatOrDogOrBoth = {name: 'John', wags: false};
    // 类型错误, 同上
    let cat4: CatOrDogOrBoth = {barks: true, wags: false};
    // 属于Cat类型,因为没有barks属性,即不是Dog类型,且完全拥有Cat类型定义的所有属性
    let cat5: CatOrDogOrBoth = {name: 'John', purrs: true, wags: false};
    // 既是Cat类型也是Dog类型
    let cat6: CatOrDogOrBoth = {name: 'John', barks: false, wags: false, purrs:false}
    
  • 相关阅读:
    python打印出当下的小时、分钟
    flask_ajax登录注册
    flask_SQlalchemy的复杂使用
    flask使用现有的数据表、在网页中显示数据
    js 的DOMdocument的使用
    pymysql的是使用
    通过ajax修改div id="div1" 的值
    关于django2.2使用xadmin的方法
    DOS windows 使用bat脚本获取 IP MAC 系统信息
    apache https 双向证书生成
  • 原文地址:https://www.cnblogs.com/ywxgod/p/11730023.html
Copyright © 2020-2023  润新知