关于typescript:Typescript学习笔记

39次阅读

共计 7082 个字符,预计需要花费 18 分钟才能阅读完成。

为什么应用 Typescript?

微软推出 TypeScript 次要是为实现两个指标:

  • 为 Javascript 提供可选的类型零碎;
  • 兼容以后及将来的 JavaScript 的个性。

动态类型带来的益处:

  • 有利于代码重构,它在编译器编译的时候就能捕捉谬误。
  • 类型明确有利于浏览。

JavaScript 常见语法

TypeScript 是 JavaScript 的“超集”,typescript 将 javascript 语法标准化。

  1. == 与 ===

    应用 == 进行比拟时,会进行隐式转换。

    2 == 2 true
    2 == '2' true
    2 === '2' false
  2. 援用

    除字面量外,JavaScript 中的任何对象(包含函数、数组、正则表达式等)都是一个援用。

  3. null 和 undefined

    变量没有初始化:undefined。变量不可用为 null。

    undefined == undefined true
    undefined == null true
    // 查看变量是否初始化
    if(typeof val !== 'undefined'){}
  4. this

    this 关键字指向调用上下文

    function foo(){console.log(this)} /** this --> window **/
    var obj = {foo:function(){console.log(this)}} 
    obj.foo() /** this --> obj */ 
  5. 闭包

    外部函数拜访内部变量,此时内部函数的变量被外部函数绑定,称为闭包。

    function outer(){
      var outerVal = '1'
      function inner(){console.log(outerVal)
      }
      outer()}
    /** inner 绑定了 outerVal */
  6. 数字

    JavaScript 中数值是双精度的 64 位的 number

    console.log(.1 + .2) // 0.30000000000000004

内置整数类型限度 Number.MAX_SAFE_INTEGER-Number.MIN_SAFE_INTEGER

金融计算中个别应用 big.js

NaN,计算出的后果不是非法数值时返回 NaN,检测 NaN,Number.isNaN。

  1. thuthy

!!双感叹号,第一个!是将值转为布尔值,第二个逻辑反转。

ES6 语法

  1. class

    /*ES6*/
    class Point {
      x: number
      y: number
      constructor(x: number, y: number) {
        this.x = x
        this.y = y
      }
      add(point: Point) {return new Point(this.x + point.x, this.y + point.y)
      }
    }
    
    /* 编译后 ES5*/
    var point = function(){function Point(x, y){
        this.x = x;
        this.y = y;
      }
      Point.prototype.add = function(point){return  new Point(this.x + point.x, this.y + point.y)
      }
      return Point;
    }()

继承

/*ES6*/
class Point3D extends Point {
  z: number
  constructor(x: number, y: number, z: number) {super(x, y)
    this.z = z
  }
  add(point: Point3D) {var point2D = super.add(point)
    return new Point3D(this.x + point2D.x, this.y + point2D.y, this.z + point.z)
  }
}

/* 编译后 ES5*/
var point3D = function(_super){__extends(Point3D, _super)
  function Point3D(x, y, z){_super.call(this, x, y)
    this.z = z;
  }
  Point3D.prototype.add = function(point){var point2D = _super.prototype.add.call(this, point)
   return new Point3D(this.x + point2D.x, this.y + point2D.y, this.z + point.z)
  }
  return Point;
}(Point)

/**__extends typescript 编译 extends 时生成 */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({__proto__: [] } instanceof Array && function (d, b) {d.__proto__ = b;}) ||
        function (d, b) {for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
/*
d 示意派生类,b 示意基类
*/
  return function (d, b) {extendStatics(d, b); // 拷贝动态变量
        function __() { this.constructor = d;} // 保留派生结构器
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); //d.prototype.__proto__ = b.prototype
    };
})();

辨别 proto prototype

javascript 中所有对象都有属性__ proto __

/** 查找属性程序 
obj.property
obj.__proto__.property
obj.__proto__.__proto__.property
**/

javasript 所有的函数都有属性 prototype,prototype 有个指向函数自身的结构器 constructor。

function Foo(){this.name = "xm"}
var foo = new Foo();
/** 通过函数创立的对象,会将函数 prototype 传给对象__proto__*/
console.log(foo.__proto__ === Foo.prototype)
  1. 箭头函数

    var inc = x => x + 1;

箭头函数带来语法简洁和 this 失落问题。

  1. rest 参数

    …+ 参数名的模式示意最初一个参数,获取时转为数组。

  2. let 和 const

    var 变量是函数作用域,let 变量块作用域

    /** 闭包中的 var*/
    var funcs = []
    for(var i = 0;i < 3; i++){funcs.push(function(){console.log(i)
      })
    }
    for(var j = 0;j < 3; j++){funcs[j]();}
    /* 输入 3*/

const 申明常量值。

  1. 解构

    反对对象和数组解构。

    /* 对象解构 */
    var person = {name:'x',age:12,gender:1}
    var {name, age} = person
    console.log(name, age) // x, 12
    var {x, y, ...remaining} = {x: 1, y: 2, z: 4, w: 5} // 看作删除了 x,y
    console.log(x,y,remaining) // 1,2 {z:4,w:5}
  2. 扩大运算符

    Function.prototype.apply

    /*apply 调用 */
    function foo(x,y){}
    var args = [0,1]
    foo.apply(null, args)
    // 新语法
    foo(...args)
    // 数组追加元素
    var list = [1, 2]
    list = [...list, 3] //  [1,2,3]
    list = [0,...list,4] // [0,1,2,3,4]
  3. for…of

    /*for...in*/
    for(var e in [7,8,9]){console.log(e) }// 返回索引
    for(var e of [7,8,9]){console.log(e) }// 返回元素
  4. Promise

    应用 Promise 解决异步和回调函数。

    var promise = new Promise((resolve, reject) => {resolve()// 回调正确值
                                                   reject() // 异样值})
    promise.then(res => {}) // 失常
    .catch(err => {}) // 异样

并行流程管制,Promise.all([promise1,promise2]).then(res => [result1, result2])

  1. generators

    function* idGen(){
        let index = 0
        while(index < 3) yield /* 暂停 */ index++;
    }
    var id = idGen();
    console.log(id.next());
    console.log(id.next());
    console.log(id.next());
    console.log(id.next());
  2. async/await

    async function foo(){var result = await exPromise() // 期待 promise 执行返回
        console.log(result)
    }

TS 我的项目形成

  1. 编译上下文

    tsconfig.json 配置文件,配置选项:tsconfig

  2. 申明空间

    类型申明空间和变量申明空间。

    • 类 (class): 类型 , .
    • 接口 (interface): 类型.
    • 枚举 (enum): 类型 , .
    • 类别名 (type): 类型.
    • 函数 (function): .
    • 变量 (let, const, var, parameters): .
  3. 模块

    默认状况下申明处于全局命名空间中。应用 export 变成文件模块。

    模块门路查找

    /** 相对路径 **/
    import * as foo from './foo' // 同级目录
    import * as foo from '../foo' // 下级目录
    import * as foo from '../someFolder/foo // 绝对目录
    
    /** 导入门路不是相对路径时,动静查找 **/
    import * as foo from 'foo'
    /*
    查找程序
    ./node_modules/foo
    ../node_modules/foo
    ../../node_modules/foo
    */
    import * as foo from 'something/foo'
    /**
    ./node_modules/something/foo
    ../node_modules/something/foo
    ../../node_modules/something/foo
    */
    /* place */
    import * as foo from 'foo'
    /** 查找程序 */
    /**
    foo 是文件 foo.ts
    foo 是目录 foo/index.ts
    foo 是目录 foo/package.json 有 types
    foo 是目录 foo/package.json 有 main
    **/
  4. 命名空间

    //typescript 申明
    namespace Utility {export function log(msg) {console.log(msg);
      }
      export function error(msg) {console.log(msg);
      }
    }
    // usage
    Utility.log('Call me');
    Utility.error('maybe');
var Utility;
(function (Utility) {function log(msg) {console.log(msg);
    }
    Utility.log = log;
    function error(msg) {console.log(msg);
    }
    Utility.error = error;
})(Utility || (Utility = {}));
// usage
Utility.log('Call me');
Utility.error('maybe');
  1. 动静导入表达式

    // 动静加载
    import(/* webpackChunkName: "momentjs" */ 'moment')
      .then(moment => {
        // 懒加载的模块领有所有的类型,并且可能按期工作
        const time = moment().format();
        console.log('TypeScript >= 2.4.0 Dynamic Import Expression:');
        console.log(time);
      })
      .catch(err => {console.log('Failed to load moment', err);
      });

创立 TS 我的项目

  1. 装置 node 环境,创立目录进入执行 npm init -y;
  2. 装置 ts npm install typescript –save-dev ;
  3. 创立文件 node.d.ts npm install @types/node –save-dev;
  4. 初始化 tsconfig.json npx tsc –init –rootDir src –outDir lib –esModuleInterop –resolveJsonModule –lib es6 , dom –module commonjs;
  5. 增加 ts-node:npm install ts-node –save-dev 实现实时编译和运行;
  6. 增加 nodemon:npm install nodemon –save-dev,只有文件被扭转,它就会调用 ts-node。

TS 类型零碎

  1. 基本概念

    根本类型 number string boolean string[]

    接口 interface

    非凡类型 any、null、undefined 和 void

    // 接口
    interface Name{
        first: string,
        last: string
    };
    let n : Name;
    n = {
        first: 'Li',
        last:'p'
    }
    // 泛型
    function contact<T>(items : T[]): T[]{
        //......
        return items;
    }
    // 联结类型
    function join(items : string[] | string){//......}
    // 穿插类型
    function extend<T, U>(first: T, last : U) :T & U{const result = <T & U>{}
        return result
    }
    // 元祖类型
    let nameNum : [string, number]
    // 类型别名
    type mind = string | Number
    let m : mind
  2. @types

    仓库 @types 通过配置 tsconfig.json 的 compilerOptions.types 管制全局。

  3. 环境申明

    应用关键字 declare 进行申明,个别放在.d.ts 文件。

  4. 枚举

    数字枚举和字符串枚举。

  5. lib.d.ts

    装置 TypeScript 时,会顺带装置一个 lib.d.ts 申明文件。这个文件蕴含 JavaScript 运行时及 DOM(Document Object Model,文档对象模型)中存在的各种常见的 JavaScript 环境申明。

  6. 函数

    申明函数 type inc = (num : number) => number

  7. 可调用可实例化

    // 可调用
    interface ReturnStr{() : string;
    }
    declare const foo : ReturnStr
    const str = foo() // str 字符串
    // 内联注解
    const overload: {(foo: string): string;
     (foo: number): number;
    } = (foo: any) => foo
    // 可实例化
    interface NewAble {new (): string;
    }
    declare const newAble: NewAble;
    const foo = new newAble
  1. 类型断言

    Ts 能够以任何形式去重写其推断和剖析的类型,称为类型断言。

    interface Foo{Bar : string}
    const f1 = {} as Foo;
    f1.bar = "1";
    const f2 = <Foo>{};
    f2.bar = "2";
  1. Freshness

    查看字面量类型

    function hasName(some: { name: string}) {
      some.name = "name"; // 正确
      some.age = 12; // 谬误
    }
  1. 类型爱护

    typeof(typeof x === ‘string’)

    instanceof (foo instanceof Foo)

    in 查看对象是否存在对应属性

  2. readonly

    type Foo = {readonly bar: string;};
    const f: Foo = {bar: "x"};
    f.bar = "y"; // 谬误,不可批改
  1. 泛型

    类的实例成员、类的办法、函数的参数、函数返回值之间的束缚。

  2. never

    never 类型就是 TypeScript 中的底部类型。用于一个总会抛出谬误的函数或一个总会抛出谬误的函数。

    never 与 void 的差别,void 示意没有任何类型,never 示意永远不存在的值的类型。

  3. 异样解决

    try {throw new Error("err.");
    } catch (error) {console.log(error)
    } 

代码格调约定

  1. 应用 camelCase 模式为变量和函数命名。
  2. 应用 PascalCase 模式为类命名。
  3. 应用 PascalCase 模式为接口命名。
  4. 类型别名应用 PascalCase 模式进行命名。
  5. 命名空间应用 PascalCase 模式进行命名。
  6. 枚举类型应用 PascalCase 模式进行命名。
  7. 对于须要明确表明不可用的状况,null 和 undefined 都不倡议应用。
  8. 格式化

    tsfmt 命令格式化,应用单引号,空格两 tab,如果想用 extends 或 implements,则倡议应用 interface。

TS 编译原理

….. 待续再看

正文完
 0