美文网首页
TypeScript疑难解析

TypeScript疑难解析

作者: zxhnext | 来源:发表于2020-05-18 18:04 被阅读0次

    1. 语言类型

    1.1 强类型与弱类型

    强类型不允许随意的隐式类型转换,而弱类型是允许的
    强类型和弱类型区别是是否允许随意的隐式转换
    强类型是语法层面限制类型,如果类型不对,编译阶段就会报错。而js只能在运行阶段通过类型判断去限制。这也就意味着JS只能到代码运行到这一行时才能发现错误,不能像其它语言编译阶段就可以发现错误

    强类型优势:

    1. 更早发现错误(编译阶段就可发现错误,不用等到代码运行)
    2. 代码更智能,编码更准确
    3. 重构更牢靠
    4. 减少不必要的类型判断

    1.2 静态类型与动态类型

    静态类型:一个变量声明时它的类型就是明确的,声明过后,它的类型就不允许再修改
    动态类型:运行阶段才能够明确变量类型,而且变量类型随时可变
    静态类型与动态类型区别是是否允许随时修改变量类型


    image.png

    JS是弱类型,动态类型

    2. TS简介

    下面这张图可以让我们充分的理解什么是TS


    image.png

    3. TS环境配置

    3.1 生成ts配置文件

    tsc --init
    

    3.2 将报错信息设置为中文

    tsc --locale zh-CN
    

    vs code中在设置里搜索typescript locale,改为中文即可

    4. ts的几种数据类型

    const a: string = "foobar";
    const b: number = 100; // NaN Infinity
    const c: boolean = true;
    // const d: boolean = null;
    const e: void = undefined; // 非严格模式下也可以赋值null, 严格模式下只能赋值undefined
    const f: null = null;
    const g: undefined = undefined;
    const h: symbol = Symbol(); // es5中不能使用Symbol(),包括es6中的Promise等, 解决办法,在配置文件中添加"lib": ["es2015", "DOM"], DOM是默认的的,不开启lib时默认就有
    

    5. 定义类型

    5.1 object

    ts中的object包括{}, [], function

    const foo: object = {} // [] // function() {}
    

    但是如果仅仅想声明对象,需要使用对象字面量语法

    const obj: {} = {};
    

    5.2 array

    const arr1: Array<number> = [1, 2];
    const arr2: number[] = [1, 2, 3];
    

    5.3 元组

    元组是明确元素数量与元素类型的数组
    常见用于函数返回值

    5.4 枚举

    常见用于用某几个数值代表某种状态

    let state = 0; // 0, 1, 2三种状态
    
    enum PostStatus {
      Draft, // = 0
      UnPublished, // = 1
      Published, // = 2
    }
    
    // 编译后
    (function (PostStatus) {
        PostStatus[PostStatus["Draft"] = 0] = "Draft";
        PostStatus[PostStatus["UnPublished"] = 1] = "UnPublished";
        PostStatus[PostStatus["Published"] = 2] = "Published";
    })(PostStatus || (PostStatus = {}));
    

    如果是字符串枚举,因为无法自增,所以就必须给每一个成员手动添加值

    enum PostStatus {
      Draft = 'aaa'
      UnPublished = 'bbb'
      Published = 'ccc'
    }
    

    枚举会侵入代码,建议使用常量枚举,即在枚举前加const

    const enum PostStatus {
      Draft, // = 0
      UnPublished, // = 1
      Published, // = 2
    }
    

    5.5 函数

    1. 函数声明
      行参和实参数量必须相等
    function func1(a: number, b: number): string { 
        return 'str'
    }
    func1(100, 200)
    
    1. 可选参数
    function func2(a: number, b?: number): string {
      return "str";
    }
    // 或者使用默认参数
    function func3(a: number, b: number = 10): string {
      return "str";
    }
    
    1. 传入多个参数
    function func4(a: number, b: number, ...rest: number[]): string {
      return "str";
    }
    
    1. 函数表达式
    const func5: (a: number, b: number, ...rest: number[]) => string = function (
      a: number,
      b: number
    ): string {
      return "str";
    };
    

    6. any(任意参数)

    6.1 隐式类型推断

    let age = 10; // 隐式推断为number类型
    age = "str"; // 赋值string类型时报错
    
    let foo; // 声明并未赋值,此时推断为any类型,下面先赋值number,再赋值string,也不会报错
    bar = 10; // any
    bar = "str"; // any 
    

    6.2 类型断言

    类型断言有as或者<><>在jxs语法中会和标签产生冲突,所以推荐使用as

    const nums = [100, 200, 300, 400];
    const res = nums.find((i) => i > 0);
    
    const num1 = res as number;
    const num2 = <number>res;
    

    7. 接口

    7.1 只读 readonly

    7.2 动态属性

    如果不确定有几个值,可以用以下方法

    interface cache {
      [key: string]: string
    }
    

    8. 类

    最新的语法中,不再在construction通过this来动态添加属性,而是在外面对每个属性声明

    // 如果没有在外部设置属性值,那就要在construction中设置属性值
    class Person {
      name: string = "init name"
      age: number
      constructor(name: string, age: number) {
        this.name = name // 不再直接通过this来动态添加属性,而是需要在外面声明
        this.age = age
      }
    }
    

    8.1 修饰符

    public
    private
    protected(可以在子类获取,外部获取不到)

    注意:如果给constructor设置了private,那么外部就不能实例化了,但是内部可以访问到,所以这是我们在内部加一个静态方法,去返回实例

    class Student extends Person {
      private constructor(name: string, age: number) {
        super(name, age)
        console.log(this.gender)
      }
      static create(name: string, age: number) {
        return new Student(name, age)
      }
    }
    
    const jack = Student.create("jack", 18)
    console.log(jack.name)
    console.log(jack.age)
    console.log(jack.gender)
    

    8.2 只读属性readonly

    8.3 类与接口

    接口仅定义公共能力,而不做具体方法实现,建议一个接口只实现一个功能

    interface Eat {
      eat(food: string): void
    }
    
    interface Run {
      run(distance: number): void
    }
    
    class Person implements Eat, Run {
      eat(food: string): void {
        console.log(`优雅的进餐,${food}`)
      }
      run(distance: number): void {
        console.log(`直立行走:${distance}`)
      }
    }
    
    class Animal implements Eat, Run {
      eat(food: string): void {
        console.log(`呼噜呼噜的吃,${food}`)
      }
      run(distance: number): void {
        console.log(`爬行:${distance}`)
      }
    }
    

    8.4 抽象类

    与接口类似,如果比较复杂的类建议使用抽象类
    注意:抽象类无法new,只能继承

    abstract class Animal {
      eat(food: string): void {
        console.log(`呼噜呼噜的吃,${food}`)
      }
      abstract run(distance: number): void
    }
    
    class Dog extends Animal {
      run(distance: number): void {
        console.log(`爬行:${distance}`)
      }
    }
    

    9. 泛型

    function createNumberArray(length: number, value: number): number[] {
      const arr = Array<number>(length).fill(value)
      return arr
    }
    
    function createStringArray(length: number, value: string): string[] {
      const arr = Array<string>(length).fill(value)
      return arr
    }
    
    function createArray<T>(length: number, value: T): T[] {
      const arr = Array<T>(length).fill(value)
      return arr
    }
    
    const resResult = createArray<string>(3, "foo")
    

    10. 类型声明

    如果一个成员在定义时没有声明类型,那么在使用时可以为他声明类型

    import { camelCase } from 'lodash'
    declare function camelCase(input: string): string
    const res = camelCase('hello typed')
    

    一般第三方库都有单独的类型声明模块,例如lodash的声明模块@types/lodash

    相关文章

      网友评论

          本文标题:TypeScript疑难解析

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