• Typescript学习笔记


    什么是 TypeScript

    TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript。

    安装 TypeScript

    命令行工具安装:

    npm install -g typescript

    编译一个 TypeScript 文件:

    tsc hello.ts

    原始数据类型/ 任意值

    为每一个变量提前申明该类型,则该变量取值只能为申明的类型,否则报错

    如果一个变量可以任意取值,可以通过any 申明该变量为任意值

    原始数据类型包括:布尔值(boolean)、数值(number)、字符串(string)、nullundefined、Symbol(ES6)共六种

    申明为number类型的变量,后面可以取值类型为 number  、nullundefined,会默认进行隐式转换

    例子:

    let isDone: boolean = false;        //申明该值为 boolean 类型
    
    let decLiteral: number = 6;
    
    let notANumber: number = NaN;       // 进行隐式转换
    
    let infinityNumber: number = Infinity;  // 进行隐式转换
    
    let num: number = undefined;   // 进行隐式转换
    
    let myName: string = 'Xcat Liu';
    
    let u: undefined = undefined;
    
    let n: null = null;
     
    let anytest: any = 123;   //申明该值为任意类型
    anytest = true;
    anytest = '任意值'
    
    //  内置对象类型申明
    
    let b: Boolean = new Boolean(1);    // 申明为 Boolean 类型
    
    let e: Error = new Error('Error occurred');    //申明为错误类型
    
    let d: Date = new Date();   // 申明为 时间类型
    
    let r: RegExp = /[a-z]/;    //申明为正则类型

    let body: HTMLElement = document.body;
    let allDiv: NodeList = document.querySelectorAll('div');
    document.addEventListener('click', function(e: MouseEvent) { // Do something });
     
    提前申明变量的类型也可以用在functiuon函数传参,用于规定该参数的类型

    在 TypeScirpt 中,可以用 void 表示没有任何返回值的函数

    例子:
    function sayHello(person: string) {     // 在函数出入的参数后面申明类型
        return 'Hello, ' + person;
    }
    
    
    function test(): void {     //void 表示该函数没有返回值
      alert('Hello Wrold');
    }
     

    联合类型

    联合类型表示取值可以为多种类型中的一种。使用 | 分隔每个类型。

    let test: string | number;    //申明 test变量的类型为string 或者 number其中一种
    test = 'seven';     //test的取值可以为其中一种类型
    test = 7;

    当不确定一个使用了联合类型的变量是哪种类型时,只能访问此联合类型的所有类型里共有的属性或方法

    function getString(something: string | number) {     //申明传入的参数为string或者number类型
      return something.toString();        // 只能调用string和number共有的方法
    }

    错误例子:

    function getLength(something: string | number) {
      return something.length;       // number类型不存在length
    }

    对象的类型——接口 (interfaces)

    即提前定义一个对象的类型规则,用于申明一个对象时进行类型匹配

    interface Person {     //使用interface定义一个对象的类型,取名Person    首字母一般大写
      name: string;        //申明该对象每个值的取值类型
      age: number;
    }
    
    let xcatliu: Person = {     // 申明一个xcatliu对象,使用Person规则进行匹配验证
      name: 'Xcat Liu',
      age: 25,
    };

     使用Interfaces来定义对象的类型,定义了类型的对象,定义的变量不允许比类型少,也不能多,结构必须一模一样

    错误例子:

    interface Person {
      name: string;
      age: number;
    }
    
    let xcatliu: Person = {    //不能比定义的Person类型的变量少
      name: 'Xcat Liu',
    };
    
    let xcatliu: Person = {
      name: 'Xcat Liu',
      age: 25,
      website: 'http://xcatliu.com',   /不能比定义的Person类型的变量多
    };

      

    如果我们希望不要完全匹配一个 类型,可以使用可选属性: 可选属性的含义是该属性可以不存在。使用 ?      但是仍然不允许添加未定义的属性

    interface Person {
      name: string;
      age?: number;      //在属性后面加上? 表示该属性可有可无
    }
    
    let xcatliu: Person = {
      name: 'Xcat Liu',
    };

    有时候我们希望一个接口允许有任意的属性,即可以任意添加属性个数,使用 任意属性  [propName: string]

    一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性    任意属性的取值类型为 any ,否则会跟可选属性冲突

    interface Person {
      name: string;
      [propName: string]: any;     // 表示可以任意添加属性个数  ,添加的属性类型为 any
    }
    
    let xcatliu: Person = {
      name: 'Xcat Liu',
      website: 'http://xcatliu.com',   //任意添加的属性
      websit2: 'http://xcatliu.com',    //任意添加的属性
    };

     对象中的一些字段只能在创建的时候被赋值,那么可以用 readonly 定义只读属性,在刚刚创建对象的时候赋值,后面不允许改变该属性值。也不能在创建的时候未定义值

    readonly 定义在属性的前面,用空格区分

    interface Person {
      readonly id: number;   //使用 readonly 定义只读属性
      name: string;
    }
    
    let xcatliu: Person = {
      id: 89757,
      name: 'Xcat Liu',
    };
    
    xcatliu.id = 9527;    //报错  不能改变该属性值

    数组的类型

    数组的类型用于定义申明一个数组时的格式,申明格式类型的数组不能使用其他类型的方法

    对象中的接口定义类型方法也同样适用于数组

    let testArr: number[] = [1,2,5,4,8]     //申明一个数组的类型为 number
    
    let fibonacci: string[] = ["1","2"];    //申明一个数组的类型为 string
    
    let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];   // 申明一个数组的类型为任意类型
    
    let fibona: Array<number> = [ 1, 2, 3, 5];   //也可以使用数组泛型Array<elemType> 来表示数组
    
    interface NumberArray {      //使用接口定义一个数组的类型,表示该数组取值必须为 string 类型
      [index: number]: string;
    }
    let fi: NumberArray = ["a","1"];
    
    interface NumberArr {        //使用接口定义一个数组的类型,表示该数组取值必须为 number 类型
      [index: number]: number;
    }
    let fi2: NumberArr = [1, 1, 2, 3, 5];

    类数组不是数组类型,比如 arguments  ,不能使用数组的类型定义方式

     常见的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection 等

    function sum() {
      let args: IArguments = arguments;    // arguments是类数组类型,使用 IArguments
    }

    函数的类型

    定义函数的类型,对函数传入的参数和返回值做一定的限制

    输入多余的(或者少于要求的)参数,是不被允许的,

    function sum(x: number, y: number): number {     //申明一个函数sum  限制其传入的参数为 number类型,返回的参数为 number类型
      return x + y;
    }
    
    sum(1, 2);

    如果是一个函数表达式,,那么需要对左右两边进行类型的限制

    //申明了一个 mySum函数,申明其类型为number
    let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
      return x + y;
    };

     函数的类型定义同样可以使用对象的接口

    interface SearchFunc {      //使用接口申明一个类型,名称为 SearchFunc
      (source: string, subString: string): boolean;     //申明该函数的传入值都为 string   返回值为 boolean
    }
    
    let mySearch: SearchFunc;     //申明一个函数,使用 SearchFunc 类型规则
    mySearch = function(source: string, subString: string) {
      return source.search(subString) !== -1;
    }

    函数的类型也可以定义可选的传入参数, 在参数后面使用 ?

    可选参数必须接在必需参数后面

    function buildName(firstName: string, lastName?: string) {    // lastName 为可选参数
      if (lastName) {
        return firstName + ' ' + lastName;
      } else {
        return firstName;
      }
    }
    let xcatliu = buildName('Xcat', 'Liu');
    let xcat = buildName('Xcat');

    TypeScript 会将添加了默认值的参数识别为可选参数     使用默认值的可选参数不限制位置

    function buildName(firstName: string, lastName: string = 'Liu') {     // lastName 为可选参数
      return firstName + ' ' + lastName;
    }
    let xcatliu = buildName('Xcat', 'Liu');
    let xcat = buildName('Xcat');

    function reverse(x: number | string): number | string {
      if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
      } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
      }
    }

    ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数,items 是一个数组。可以用数组的类型来定义它:

    function push(array: any[], ...items: any[]) {     //...items表示剩余参数,是一个数组,可以申明为任意类型的数组
      items.forEach(function(item) {
        array.push(item);
      });
    }
    
    let a =  [];
    push(a, 1, 2, 3);

    类型断言   <类型>值     值 as 类型

    类型断言可以用来绕过编译器的类型推断,手动指定一个值的类型

    TypeScript在使用联合类型时,默认不能引用不确定类型的方法,只能引用共有的方法,某些时刻,我们需要使用类型断言,即申明此时的属性为某个类型

    类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的   断言的类型必须是联合类型中的某一个

    function getLength(something: string | number): number {
      if ((<string>something).length) {   // 默认不能使用 length属性,使用类型断言 <string>   将此时的something申明为 string类型
        return (<string>something).length;
      } else {
        return something.toString().length;
      }
    }

    类型别名

    类型别名用来给一个类型起个新名字。使用 type

    type Name = string;        // 使用 type 将string类型起名为 Name
    type NameResolver = () => string;      //另一种写法
    type NameOrResolver = Name | NameResolver;     //使用该别名
    function getName(n: NameOrResolver): Name {
      if (typeof n === 'string') {
        return n;
      }
      else {
        return n();   
      }
    }

    字符串字面量类型

    字符串字面量类型用来约束取值只能是某几个字符串中的一个。同样使用 type

    type test = 'click'|'scroll'|'mousemove'       // 使用 type 规定test变量为三个值其中一个
    function handleEvent(ele: Element, event: test) {   //使用test类型,传入的值为规定值的其中一个
      // do something
    }
    handleEvent(document.getElementById('hello'), 'scroll');  

    元组

    数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。

    简单理解,在数组类型中,要么规定数组中的每个值都为某种类型,要么都为任意类型。使用元组,可以依次给每个值指定类型

    let xcatliu: [string, number] = ['Xcat Liu', 25];

    我们也可以在定义数组类型后,通过索引依次赋值,也可以只赋值其中一项

    当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项。

    let xcatliu: [string, number];    //先定义每个值的类型
    xcatliu[0] = 'Xcat Liu';     // 通过索引赋值
    xcatliu[1] = 25;
    
    xcatliu[0].slice(1);     //可以通过索引调用对应类型的方法
    xcatliu[1].toFixed(2);


    let xcatliu: [string, number] = ['Xcat Liu'];   //报错,需要全部赋值

    当我们去访问数组未定义的下标或者对其进行赋值时,它的类型为已存在元素的类型组成的联合类型,能够调用的方法为联合类型共有的方法

    let xcatliu: [string, number];
    
    xcatliu = ['Xcat Liu', 25, 'http://xcatliu.com/'];    // 第三个值的类型为 string|number
    
    xcatliu.push(true);     // 报错   true 是 boolean 类型
    
    console.log(xcatliu[2].slice(1));   // 报错   slice不是 string|number 共有的方法

    TypeScript 中类的用法    public privateprotected

    • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
    • private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
    • protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
    class Animal {
      public name;           //表示公共的,在任何地方都可以被访问
      private age;          //表示私有的,不允许被访问,也不能继承
      protected height;     //表示受保护的,只能通过继承访问
      public constructor(name) {
        this.name = name;
      }
    }
    
    var a = new Animal('Jack');
    console.log(a.name);        
    console.log(a.age);      //报错,不允许被访问
    console.log(a.height);  // 报错,只能通过继承访问

    abstract 用于定义抽象类和其中的抽象方法 

     抽象类是不允许被实例化的,即不能通过new去实例化,只能被继承

    抽象类中的抽象方法必须被子类实现,即使用abstract 定义为抽象方法,那么必须在子类实现

    abstract class Animal {
      public name;
      public constructor(name) {
        this.name = name;
      }
      public abstract sayHi();     //抽象方法
    }
    
    class Cat extends Animal {
      public sayHi() {     // 继承 Animal类后实现定义的抽象方法
        console.log(`Meow, My name is ${this.name}`);    
      }
    }
    
    let cat = new Cat('Tom');

    类实现接口  implements

    不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。

    interface Alarm {    //使用 interface 定义了一个接口,里面是一个 alert 方法
      alert();
    }
    
    class Door {
    }
     
    class SecurityDoor extends Door implements Alarm {    // SecurityDoor继承了 Door类并且引用了 Alarm 接口的方法
      alert() {
        console.log('SecurityDoor alert');
      }
    }
    
    class Car implements Alarm {      // Car类 引用了Alarm 接口的方法
      alert() {
        console.log('Car alert');
      }
    }

    一个类可以同时引用多个接口

    interface Alarm {
      alert();
    }
    
    interface Light {
      lightOn();
      lightOff();
    }
    
    class Car implements Alarm, Light {
      alert() {
        console.log('Car alert');
      }
      lightOn() {
        console.log('Car light on');
      }
      lightOff() {
        console.log('Car light off');
      }
    }

     接口与接口之间也可以相互继承:

    interface Alarm {
      alert();
    }
    
    interface LightableAlarm extends Alarm {
      lightOn();
      lightOff();
    }
     
  • 相关阅读:
    从头编写 asp.net core 2.0 web api 基础框架 (1)
    希腊字母表
    Python数据分析(二): Numpy技巧 (4/4)
    Python数据分析(二): Numpy技巧 (3/4)
    Python数据分析(二): Numpy技巧 (2/4)
    OLED液晶屏幕(3)串口读取文字并分割
    OLED液晶屏幕(2)取模软件
    OLED液晶屏幕(0)自动获取12ic地址液晶屏幕
    OLED液晶屏幕(1)OLED液晶屏幕ssd1306驱动芯片 arduino运行 ESP8266-07可以 12f不可以
    I2C 连接 12864 OLED 屏幕
  • 原文地址:https://www.cnblogs.com/zhengweijie/p/7152056.html
Copyright © 2020-2023  润新知