TypeScript 从入门到精通

作者: Danile_1226 | 来源:发表于2019-07-09 21:54 被阅读12次

    一、什么是 TypeScript

    先看一下官网上对 TypeScript 的介绍。

    图1.png

    关键词:超集
    言外之意 JavaScript 的所有用法 TypeScript 都支持。

    关键词:Type
    TypeScript 强调也是其优点之意是【类型】

    为什么需要 Ts 呢?举个小例子:
    一个杯子可以装水,也可以当笔筒装杂物。但是,拿装杂物的杯子些许显得不太干净。物有所用,各司其职
    Js 是弱类型可以定义 number 类型,可以定义 string 类型,这就并未各司其职。
    所以,这就诞生了 Ts

    二、TypeScript 的安装及运行

    安装:npm install -g typescript 或者 yarn add global typescript
    确认是否安装成功: tsc -v

    在官网中(中文网 -- 练习)可以将 Ts 转换为 Js

    图2.png

    浏览器会识别 html / css / js。识别不了 ts,所以此时我们需要将 ts 编译为 js。

    打开编辑器(确保在node/npm/typescript都成功的前提下)
    第一步:新建文件夹 TS-APP
    第二步:TS-APP下面新建一个index.html文件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <script src="./app.js"></script>
    </body>
    </html>
    

    在<script src="./app.js"></script>若src="./app.ts"会报错

    图3.png

    第三步:在TS-APP下面新建一个app.ts文件

    class Greeter {
      greeting: string;
      constructor(message: string) {
          this.greeting = message;
      }
      greet() {
          return "Hello, " + this.greeting;
      }
    }
    
    let greeter = new Greeter("world");
    
    let button = document.createElement('button');
    button.textContent = "Say Hello";
    button.onclick = function() {
      alert(greeter.greet());
    }
    
    document.body.appendChild(button);
    

    要想在浏览器运行起来,需要将 app.ts 编译转换为 app.js。此时就要进行此命令: tsc app.ts
    ✅运行完此命令之后,会自动生成一个 app.js 文件。此时浏览器打开,效果如下:

    图4.png

    问答区:如果想同时运行多个 ts 文件该如何操作。
    此时需要进行此命令 tsc --init
    命令执行成功之后,会自动生成一个 tsConfig.json 文件,此文件则会将帮助所有的 ts 文件编译转换为相应的 js 文件。
    ✅运行所有 ts 文件,tsc 即可,则会全部转换

    图6.png

    在此处,插播推荐两个插件:
    Live Server(能够保存的时候,自动更改)
    TypeScript Auto Compiler(能够保存之后,不需要执行 **tsc** 命令,自动会生成相应的 js 文件)

    三、TypeScript 入门

    (一)TypeScript -- 基本数据类型和报错解析

    为了让程序有价值,我们需要能够处理最简单的数据单元:数字,字符串,结构体,布尔值等。 TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。

    // 基本数据类型
    let num = 25;
    let float = 25.5;
    let hex = 0xf000;  // 16进制
    let binary = 0b1001; // 2进制
    let octal = 0o733;  // 8进制
    
    // 重新赋值
    num = '25';  // 会报错,可以在终端编写 tsc 进行查看错误❌,如下图7.
    
    // ts原型
    let num = 25;
    // 等同于
    // let num: number = 25;
    
    图7.png
    其他数据类型:string 、boolean 、 any

    ⚠️注意:在如下例子中:anything 赋予任何值都不会报错,是因为只是给 anything 开辟了一个空间,但是并没有定义其类型。在项目中,尽量避免需用 any,不太利于后期维护。

    //  boolean
    // ts原型
    let isLogin = false;
    // 等同于
    // let isLogin: string = false;
    
    // **----------------------** // 
    
    // string
    let str: string = 'hello Tc';
    
    // **----------------------** // 
    
    // any
    let anything; // 等同于 let anything: any
    // 没报错的原因,只是开辟了一个空间,但是没有定义其类型
    anything = 25;
    anything = 'hello'
    

    (二)TypeScript -- 数组 元组 枚举

    // 数组 元组 枚举
    let names: Array<string> = ['hello', 'word'];
    // console.log(names[0]); // hello
    // names[0] = 100; // 报错,不能将类型“100”分配给类型“string”。
    // names[0] = 'yes';
    
    let number: number[] = [1, 2, 3];
    let anyArray: any[] = [1, 'hello', true];
    
    // **----------------------** // 
    
    // 元组
    let colors: [string, number] = ['hello', 99];
    // let colors: [string, number] = [99, 'hello']; // 会报错
    
    // **----------------------** // 
    // 枚举
    enum Color{
      Black,
      Yellow,
      Red,
    }
    // let myColor: Color = Color.Black; // 输出为 0
    // let myColor: Color = Color.Yellow; // 输出为 1
    // 若Yellow = 100, 则Red为101
    

    此枚举类型,转换为 js 的时候是函数形式

    var Color;
    (function (Color) {
        Color[Color["Black"] = 0] = "Black";
        Color[Color["Yellow"] = 1] = "Yellow";
        Color[Color["Red"] = 2] = "Red";
    })(Color || (Color = {}));
    // let myColor: Color = Color.Black; // 输出为 0
    // let myColor: Color = Color.Yellow; // 输出为 1
    // 若Yellow = 100, 则Red为101
    

    控制台输出:{0: "Black", 1: "Yellow", 2: "Red", Black: 0, Yellow: 1, Red: 2}

    (三)函数相关类型

    // 函数的相关类型
    function returnValue() {
      return 'hello';
    }
    // console.log(returnValue()); // hello
    
    // 规范写法
    function returnNum(): number { // 定义其返回值类型
      return 520;
    }
    
    // **----------------------** // 
    
    // 若函数返回值 -- 空
    function sayHello(): void {
      console.log('hello @@@@@');
    }
    sayHello();
    
    
    // **----------------------** // 
    
    // 参数类型
    // 不标准写法,已经知道value1和value2的类型。
    // 报错内容:参数“value1”隐式具有“any”类型。
    // function sumVal(value1, value2) {
    //   return value1 + value2;
    // }
    
    function sumVal1(value1: number, value2: number): number {
      return value1 + value2;
      // return value1 * value2; // 如果两个参数中有一个不是数值 那么返回的是NAN。但是若为0或者'',返回0。
    }
    console.log(sumVal1(1, 2)); // 3
    // console.log(sumVal1(1, ''));
    
    function sumVal2(value1: number, value2: string): string {
      return value1 + value2;
    }
    console.log(sumVal2(1, 'hello')); // 1hello
    
    // **----------------------** // 
    
    // 函数类型
    let myFunc: (a: number, b: number) => number;
    // 若函数为定义类型,如下则都可以赋值不同类型。
    // myFunc = sayHello;
    // myFunc();
    myFunc = sumVal1; // 将函数 sumVal1 赋予给 myFunc
    console.log(myFunc(5, 5));   // 10
    

    ⚠️注意:在最开始入 ts 坑时,除开会写 any 之外。印象最深刻的是 void。fuc(): void或者fuc: () => void。类似这样的写法都没少写。但是,碰到 .then。一报错就改成 any
    void 其实是代表函数返回值为时才使用的。所以,不言而喻,.then 为什么会报错了。

    (四)对象 object & type

    // 对象 object & type
    let listObj = {
      name: 'Danile',
      age: 31
    };
    
    // 不正确写法
    //  报错内容:需要去包含 name 和 age 两个属性
    // listObj = {}; 
    
    // 报错内容:不能包含别的属性
    // listObj =  {
    //   n: 'hello',
    //   a: 12,
    // }
    
    // 最规范写法
    // let listObj(name: string, age: number) = {
    //   name: 'Danile',
    //   age: 31
    // };
    
    // **----------------------** // 
    
    // 稍微复杂对象类型
    let complex: { data: number[], myFunc: (item: number) => number[] } = {
      data: [1, 2, 3],
      myFunc: function(item: number): number[] {
        this.data.push(item);
        return this.data;
      }
    }
    // console.log(complex.myFunc(520));
    
    // **----------------------** // 
    
    // type 生成类型
    // type MyType = { data: number[], myFunc: (item: number) => number[] };
    interface MyType { data: number[], myFunc: (item: number) => number[] };
    
    let complex2: MyType = {
      data: [1, 2, 3],
      myFunc: function(item: number): number[] {
        this.data.push(item);
        return this.data;
      }
    }
    console.log(complex2.myFunc(520));
    

    ❓type 和 interface 的区别?

    (五)union type 检查类型 null undefined never

    // union type 检查类型 null undefined never
    // union type
    let unionType: number | string | boolean = 12;
    unionType = '12';
    unionType = true;
    
    
    // 检查类型
    let checkType = 10;
    if (typeof checkType == 'number') {
      console.log('number')
    }
    
    // null 和 undefined
    // let myNull = 12;
    // myNull = null; // 如果"strict": false的时候则不会有问题
    
    let myNull = null;
    myNull = undefined;  
    
    // never
    // never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never
    // 类型(除了never本身之外)。及时any也不可以赋值给never。通常表现为抛出异常或无法执行到终点(例如无限循环)
    
    let x: never;
    // x = 123; // 报错:不能将类型“123”分配给类型“never”。
    
    // never的应用场景 抛出异常
    function error(message: string): never {
      throw new Error(message);
    }
    
    // 死循环
    function loop(): never {
      while (true) {}
    }
    
    let y: number;
    y = ( () => {
      throw new Error('message');
    })();
    

    (六)class 类(属性,方法)

    ✅区分 public protected private 的区别
    public: 公共的
    private: 当成员被标记成 private时,它就不能在声明它的类的外部访问。
    protected: protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问

    // class 类(属性,方法)
    class Person {
      public name: string;
      protected gender: string;
      private age: number = 27;
      // public username: string; 
    
    
      constructor(name: string, gender: string, public username: string) {
        this.name = name;
        this.username = username;
        this.gender = gender;
      }
    
      printAge(age: number) {
        this.age = age;
        console.log(this.age);
      }
    
      setGender(gender: string) {
        this.gender = gender;
        console.log(this.gender);
      }
    }
    
    const person = new Person('Danile', '女', 'Ts');
    console.log(person.name, person.username);
    
    person.printAge(30);
    person.setGender('男');
    

    (七) class set get修饰词 用于隔离私有属性和可公开属性

    // 1.class set get修饰词 用于隔离私有属性 和 可公开属性
    // 2.class 静态属性和方法
    
    class Person1 {
      private _name: string = 'Danile_getName';
    
      // 私用属性赋值
      set setName(value: string) {
        this._name = value;
      }
    
      // 私有属性取值
      get getName() {
        return this._name;
      }
    }
    
    let person1 = new Person1();
    console.log(person1.getName);   //  Danile_getName
    person1.setName = 'Danile_setName';
    console.log(person1.getName);  //  Danile_setNames
    

    对于 set 和 get 还可以应用在校验等场景。看如下图:

    图8

    (八)namespace 命名空间

    // namespace 命名空间]
    namespace myMath {
      export const PI = 3.14;
    
      export function sumValue(num1: number, num2: number): number {
        return num1 + num2;
      }
      
      export function calcCircle(value: number) {
        return value * PI
      }
    }
    
    const PI = 2.88;
    
    console.log(myMath.sumValue(5, 10));  // 10
    console.log(myMath.PI);  // 3.14
    
    console.log(PI); //  2.88
    

    相关文章

      网友评论

        本文标题:TypeScript 从入门到精通

        本文链接:https://www.haomeiwen.com/subject/ybhzhctx.html