• 一篇够用的TypeScript总结(包含面试题及答案收录)


    TypeScript

    写在前面

    可以直接访问我的个人博客查看 -> 其他 -> typescript
    橘子海-前端笔记

    参考链接

    typescript中文手册

    AST抽象语法树

    在线开发 TypeScript

    安装 TypeScript

    • 命令行运行如下命令,全局安装 TypeScript
    npm install -g typescript
    
    • 1
    • 安装完成后,在控制台运行如下命令,检查安装是否成功(Version 4.4.3):
    tsc -v 
    
    • 1
    • 运行单独ts文件
    ts-node  [文件名.ts]
    
    • 1
    • 将ts转换为js文件
    tsc  [文件名.ts]
    
    • 1

    tsc --init 新建tsconfig.json配置文件

    基础类型

    布尔值 数字 字符串 数组 元组 枚举
    在这里插入图片描述

    原始类型

    const a:string='foobar'
    const b:number=Infinity
    const d:boolean=false
    const d: null = null
    const e: void = undefined
    const f: symbol = Symbol()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    数组类型

    const arr1: Array<number> = [1, 2, 3]//纯数字组成
    const arr2: number[] = [1, 2, 3]//常见
    //元组属于数组的一种,元组中的元素可以不必全部保持类型一致
    const foo: [number, string] = [1, 'foo']
    
    • 1
    • 2
    • 3
    • 4

    对象类型

    let obj: { foo: String, bar: number } = { foo: 'string', bar: 100 }//必须有foo/bar 数据类型正确
    let obj: { foo?: String, bar: number } = { bar: 100 }//foo可有可无
    let obj3:{ [string]: string }
    obj3.key1 = 'value123'
    obj3.key2 = 100//false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    函数类型

     function sum(a: number, n?: number) {
         return a + b
     }
     sum(10, 20)
     sum(10, '20')
    // 回调参数类型限制 
    //n?: number加了问号是可选参数
    //参数 age:number=20为默认参数
    //void 类型表示没有任何类型,一般用于定义方法的时候方法没有返回值。
    function foo(callback: (string, number) => void)) {
        callback('string', 100)
    }
    // 剩余参数 在参数的类型确定而参数个数不确定的情况时,我们需要用到剩余参数,
    //它使用 ...将接收到的参数传到一个指定类型的数组中.剩余参数必须配置到参数的最后面。
    function sum(one:string,...result:number[]):number{
        console.log(one,...result);
        return 123
    }
    sum('123',1,2,2,2,2,3,5,5)
    //接受任意参数
    ...rest:number[]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    特殊类型

    const type: 'success' | 'warn' | 'danger' = 'success'
    type StringOrNumber = string | Number
    const b: StringOrNumber = 'string' //10
    
    mixed/any类型接收任意类型
    //any弱类型 mixed强类型
    // never类型,永不存在的值类型
    //never是任何类型的子类型,可以赋值任何类型。但是没有类型是 never 的子类型或可以赋值给 never 类型,
    // 即使 any 类型也不可以赋值给never。这意味着声明 never 类型的变量只能被 never 类型所赋值。
    function error(): never {
        throw new Error('抛出错误了');
    }
    var test = (): never => {//永远拿不到返回值
      while (true) {}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    枚举类型

    给一组数值取更好的名字。数据中只会出现固定的值

    enum 枚举名 {
        标识符[= 整型常数/字符串],
        标识符[= 整型常数/字符串], 
        ...
        标识符[= 整型常数/字符串],
    };
    
    enum flag{
        pedding,
        succes='up',//字符串枚举之后,需要给后面参数赋值
        error=888,
        loading='456'
    }
    console.log(flag.pedding);//0
    console.log(flag.succes);//up
    console.log(flag.error);//888
    console.log(flag.loading);//889
    //如果标识符没有赋值,它的值就是下标。
    
    enum Color {
      red,
      blue,
      green,
    }
    
    let color: Color = Color.red;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Object类型

    • 除了原始类型的其他类型
    function getObj(options: object|string): object {//联合类型
      return {};
    }
    console.log(getObj({ xxx: 123 }));
    
    • 1
    • 2
    • 3
    • 4

    断言

    • 类型断言: 可以用来手动指定一个值的类型
    • 类型推断: TS会在没有明确的指定类型的时候推测出一个类型
      有下面2种情况:
      1. 定义变量时赋值了, 推断为对应的类型
      2. 定义变量时没有赋值, 推断为any类型
    /* 
    语法:
        方式一: <类型>值
        方式二: 值 as 类型  tsx中只能用这种方式
    */
    let nums=[110,200,300]
    let res=nums.find(i=>i>50)//res可能是number|undefind
    let num1=res as number //断言他是number类型,并非转换
    let num2=<number>res //jsx不可使用,与标签冲突
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接口

    (一种规范,约定结构)最好约束一个规范,约束对象或者函数的类型

    //定义接口
    interface Post {
      title: string;
      content: number;
      subTitle?: string;//可选成员
      readonly task: string; //只读成员
    }
    //定义函数时掉用接口
    function printPost(query: Post) {
      console.log(query.title);
      console.log(query.content);
    }
    //调用函数时 需要符合接口规范,参数&类型必须一样
    printPost({
      title: "学习ts",
      content: 789,
    });
    //定义可选参数接口
    interface myGo {
      [abckey: string]: string; //第一个string是key,第二个是value
    }
    var obj: myGo = {};
    obj.lol = "英雄联盟";
    obj.dota = "刀塔";
    obj.run = 456; //报错
    console.log(obj);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    • 用来描述一类具体对象的抽象成员
      • public:公有类型,在当前类里面、子类、类外面都可以访问 (默认)

      • protected:保护类型,在当前类里面、子类里面可以访问,在类外部没法访问

      • private:私有类型,在当前类里面可以访问,子类、类外部都没法访问

      • static : 静态方法,使用的时候类可以访问,比如Promise.all([])

      • readonly 只读属性 无法修改

    //基本使用
    class Person {
      name: string;//属性,前面省略了public关键词
      private sex: string;//属性,前面省略了public关键词
      constructor(name: string, sex: string) {//构造函数,实例化类的时候触发的方法
        this.name = name;
        this.sex = sex;
      }
      personcan(can: string): void {
        console.log(`这个${this.name}${this.sex}的,可以去${can}`);
      }
    }
    var P1 = new Person("小名", "男");
    console.log(P1.name);
    P1.personcan("吃饭");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    类与接口

    // 类与接口
    interface Eat {
      eat(food: string): void;
    }
    interface Run {
      run(distance: number): void;
    }
    // 定义类  接口约束 逗号隔开 implements后是接口约束
    class Person implements Eat, Run {
      eat(food: string): void {
        console.log("优雅永不过时的吃" + food);
      }
      run(distance: number): void {
        console.log("站着走" + distance);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    接口继承接口

    interface Person extends eat, study {
    
    }
    
    • 1
    • 2
    • 3

    abstract抽象类

    • 约束子类当中必须有某一成员
    //定义抽象类
    abstract class Animal {
      eat(food: string): void {
        console.log("动物都会吃", food);
      }
      //方法“run”不能具有实现,因为它标记为抽象(只定义不写函数)
      abstract run(distance: number): void;
      //当用了Animal抽象类之后,必须要实现run这个方法
    }
    class Pig extends Animal {
      run(distance: number): void {
        console.log("随便走", distance);
      }
    }
    var pg = new Pig();
    pg.eat("吃");
    pg.run(566);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    继承

    extends 关键字

    class Person {
      name: string;
      constructor(name: string) {
        this.name = name;
      }
    }
    class Student extends Person {
      constructor(name: string) {
        // 调用父类型构造方法
        super(name);
      }
      go() {
        // 调用父类型的一般方法
        // super.run(distance);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    get|set

    • 通过 getters/setters 来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
    class Person {
      firstName: string = "常山";
      lastName: string = "赵子龙";
      get fullName() {
        //获取时触发
        return this.firstName + "---" + this.lastName;
      }
      set fullName(value) {
        //修改时触发
        const names = value.split("---");
        this.firstName = names[0];
        this.lastName = names[1];
      }
    }
    
    const p = new Person();
    console.log(p.fullName);
    
    p.firstName = "咏春";
    p.lastName = "叶问";
    console.log(p.fullName);
    
    p.fullName = "篮球---蔡徐坤";
    console.log(p.firstName, p.lastName);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    多态

    子类重写父类的同名方法

    重载

    同一个类里面,名字是一样的,但是参数有差别(类型||个数)

    重写

    发生在父子类里面,方法名和参数也一样

    泛型

    //泛型 声明这个函数、接口或类的时候不指定具体类型 调用在指定
    function createArray<T>(length: number, value: T): T[] {
      return Array<T>(length).fill(value);
    }
    console.log(createArray<string>(25, "das"));
    console.log(createArray<number>(25, 1326));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    类型声明模块declare

    import { camelase } from "lodash";
    declare function camelase(params: string): string;
    
    • 1
    • 2

    Iterators 和 Generators

    迭代器和生成器

    装饰器

    :::tip 概念
    它是一个表达式,该表达式被执行后,返回一个函数,函数的入参分别为 target、name 和 descriptor
    ,执行该函数后,可能返回 descriptor 对象,用于配置 target 对象
    :::

    装饰器的分类

    类装饰器(Class decorators)

    // 类装饰器
    function Log(target: any) {
    console.log(target);
    console.log("in log decorator");
    }
    
    @Log
    class A {
    constructor() {
      console.log("constructor");
      // logger.log('ddd');
    }
    }
    // new A();类装饰器在没new对象的时候,js就已经执行了类装饰器的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    属性装饰器(Property decorators)

    定义属性装饰器,用来装饰类的属性。它接收两个参数:

    • target: Object - 被装饰的类
    • propertyKey: string | symbol - 被装饰类的属性名
    function logProperty(params: any) {
      // target--->类的原型对象;attr--->传入的参数url
      return function(target: any, attr: any) {
        console.log("属性装饰器;", target, attr);
        target[attr] = params;
      };
    }
    
    class HttpClient {
      @logProperty("http://www.baidu.com")
      public url: any | undefined;
      constructor() {}
      getUrl() {
        console.log("getUrl", this.url);
      }
    }
    
    console.log(new HttpClient().getUrl());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    方法装饰器(Method decorators)

    用来装饰类的方法。它接收三个参数:

    • target: Object - 被装饰的类
    • propertyKey: string | symbol - 方法名
    • descriptor: TypePropertyDescript - 属性描述符

    方法的装饰

    // 方法装饰器
    function GET(url: string) {
      console.log("entry GET decorator");
      return function(
        target: any,
        methodName: string,
        descriptor: PropertyDescriptor
      ) {
        console.log("entry GET decorator function");
        !target.$Meta && (target.$Meta = {});
        target.$Meta[methodName] = url;
      };
    }
    
    class HelloService {
      constructor() {
        console.log("constructor");
      }
      //使用
      @GET("xx")
      getUser() {
        console.log("getUser function called");
      }
    }
    new HelloService().getUser();
    // console.log((HelloService).$Meta);
    // console.log((new HelloService() as any).$Meta);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    参数装饰器(Parameter decorators)

    装饰函数参数,它接收三个参数:

    • target: Object - 被装饰的类
    • propertyKey: string | symbol - 方法名
    • parameterIndex: number - 方法中参数的索引值
    function PathParam(paramName: string) {
      return function(target: any, methodName: string, paramIndex: number) {
        !target.$Meta && (target.$Meta = {});
        target.$Meta[paramIndex] = paramName;
      };
    }
    
    class HelloService {
      constructor() {}
      getUser(@PathParam("userId") userId: string) {}
    }
    
    console.log((<any>HelloService).prototype.$Meta); // {'0':'userId'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    编译原理

    Scanner 扫描仪 Parser 解析器 Binder 绑定器 Checker 检查器 Emitter 发射器

    面试题

    类型推论 & 可赋值性

    类型推论:没给标志,ts系统推导出来的,声明的应该是什么类型

    可赋值性:数组,布尔,数字,对象,函数,类、字符串,字面量类型,满足以下任⼀条件时,A类型可以赋值给B类型。

    • A是B的⼦类型
    • A是any类型

    什么是类型断言?

    可以用来手动指定一个值的类型,定义变量时赋值了, 推断为对应的类型

    • 方式一: <类型>值
    • 方式二: 值 as 类型 tsx中只能用这种方式

    缺点:运行时可能才报错

    type 和 interface的异同

    • type(类型别名)侧重于描述类型
    • interface侧重于描述数据结构,这个结构该有哪些类型的变量

    相同点:

    • 都可以描述⼀个对象或者函数
    • interface和type都可以拓展,interface可以extends type, type也可以extends interface. 效果差不多,语法不同。

    不同点:

    • 类型别名可以⽤于其它类型 (联合类型、元组类型、基本类型(原始值)),interface不⽀持
    • interface 可以多次定义 并被视为合并所有声明成员 type 不⽀持
    • type 能使⽤ in 关键字⽣成映射类型,但 interface 不⾏。

    有哪些类型装饰器?执行的顺序是怎样的?

    类装饰器、属性装饰器、方法装饰器、参数装饰器

    执行顺序

    • 有多个参数装饰器时:从最后⼀个参数依次向前执⾏
    • ⽅法和⽅法参数中参数装饰器先执⾏。
    • 类装饰器总是最后执⾏。
    • ⽅法和属性装饰器,谁在前⾯谁先执⾏。因为参数属于⽅法⼀部分,所以参数会⼀直紧紧挨着⽅法 执⾏。

    接口类型有哪些种类

    属性类接口 函数类接口 可索引接口 类类型接口 扩展接口

    TypeScript和JavaScript的区别

    • 更规范,ts是js的超集,即你可以在ts中使用原生js语法。
    • ts在开发时能给出编译错误,js是弱类型语言需要运行时暴露
    • ts为强类型语言,代码可读性强,不允许类型随意转换,对值所具有的结构进行类型检查
    • TypeScript是面向对象的编程语言,提供了类、模块和接口,更易于构建组件和维护
  • 相关阅读:
    菊风视频能力平台通过浙江省信创适配实验室验证测试
    一本通1073;津津的储蓄计划
    制作一个简单HTML西安旅游网页(HTML+CSS)
    尚品汇后台管理项目SPU模块和SKU模块的实现
    微弱电流检测放大器PCB布线布局设计
    Spark系列之Spark体系架构
    【Unity】模型文件格式、常见3D模型格式
    1.wifi开发,wifi连接初次连接电脑没有识别,如何向esp8266中烧写代码,共享文件夹的创建
    RK3568驱动指南|第六篇-平台总线-第52章 注册platform驱动实验
    网络是怎样连接的 - 读书笔记
  • 原文地址:https://blog.csdn.net/qq_38594056/article/details/126248029