最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • TypeScript使用指南(初级篇)

    正文概述 掘金(找到Web)   2020-12-30   675

    安装编译工具

    npm install typescript -g

    基本命令

    • npx tsc --init : 初始化配置文件 tsconfig.json
    • npx tsc -w : 监听文件变化,实时编译

    基本类型

    类型

    • boolean: 布尔值
    • number: 数字,可以是整数、浮点数、各种进制
    • string: 字符串
    • Array<number>: 数组,尖括号内为数组元素的类型
    • [string, number]: 元组,有限长度的数组,可以指定每一个元素的类型
    • enum: 枚举,默认从0开始
    • unknown: 未知类型,可以是任意值,但依然会被类型检测
    • any: 任意类型,可以是任意值,编译期间不做类型检测
    • void: 空值,一般用作无返回的函数
    • null: null值,一般不使用
    • undefined: undefined值,一般用作函数默认参数的占位符
    • never: never类型,有2种情况:无法执行到最后的函数(异常,死循环),返回never的函数,常用于类型收窄(全面类型检查)
    • object: 对象类型

    类型断言

    as关键词: someValue(某变量) as string(某类型),当你比编译器了解的更多的时候,可以用类型断言来辅助编译器

    类型大小写的问题

    在ts中,都使用小写(number, string, boolean, symbol, object),大写是js中的原语类型(Number, String, Boolean, Symbol, Object),在ts中不应该被使用

    接口

    接口类型

    • 对象:指定对象属性的类型
    • 函数:指定函数参数和返回值的类型
    • 索引:指定索引的类型,比如number,string。如果是string,则索引既可以是string,也可以是number。如果是number,则索引只能是number
    • 类:指定类的构造函数、实例属性和方法,定义一个类必须同时定义2个接口,一个是构造函数的,一个是实例属性和方法的
    • 混合:指的是即是函数也是对象的一种类型,可以像函数一样调用,可有自己的属性和方法

    属性类型

    • 可选属性:用问号,例:color?: string
    • 只读属性:用readonly关键词,例:readonly color: string

    属性检查

    编译器会对实现接口的函数调用,进行属性检查,如果传入参数直接是对象本身,会对接口定义之外的属性报错,有两种办法解决该问题

    • 使用as关键词做类型断言
    • 使用变量去承载该对象,传入变量到参数

    :尽可能地不要使用接口定义之外的属性,实在不行,就用as关键词

    继承

    • 接口继承接口:相当于直接copy所有的属性,可以同时继承多个
    • 接口继承类:同上copy所有属性,包括private和protected,但该接口的实现类必须是该类本身或者是该类的子类

    函数

    声明式函数

    function myAdd (x: number, y: number): number {
      return x + y
    }
    

    赋值式函数

    let myAdd: (x: number, y:number) => number = function(x: number, y: number): number {
      return x + y
    }
    

    类型推断

    针对赋值式函数,可以省去一边的类型定义,因为编译器会根据另一边推断出具体类型

    let myAdd = function(x: number, y: number): number {
      return x + y
    }
    
    let myAdd2: (x: number, y:number) => number = function(x, y) {
      return x + y
    }
    

    参数类型

    • 可选参数:用问号,color?: string
    • 默认参数:用等号,color = '#000000'
      • 默认参数的字面量会让编译器推断出具体类型,所以无需再加上类型定义
      • 默认参数也是可选参数
    • 剩余参数:用...,(x: number, ...restOfNumber: Array<number>)

    this参数

    函数第一个参数如果是this,则是对this的类型约束,没有特定需要,一般不去设置this参数

    重载

    定义多个同名函数,最后一个函数为具体实现,前面的函数为参数声明

    :ts的函数重载只是为了类型检测,与其他语言可能会有差异

    字面量类型

    • 字符串
    • 数字
    • 布尔值

    并集和交集类型

    • 并集:let pet = Fish | Bird
    • 交集:let dom = Dom & Event

    继承

    class Animal {
      move(x: number = 0) {
        console.log(`Animal moved ${x}m.`);
      }
    }
    
    class Dog extends Animal {
      bark() {
        console.log("Woof! Woof!");
      }
    }
    
    const dog = new Dog();
    dog.bark();
    dog.move(10);
    dog.bark();
    

    修饰符

    • public: 都可使用
    • private:只有本类可以使用,子类和外部实例不允许使用,es6的私有属性也支持,如:#name: string
    • protected: 只有父类和子类的函数可以使用,外部实例不允许使用
    • readonly:只读属性,只有定义和构造函数可以给这些属性赋值

    参数属性

    构造函数的参数如果带有任意修饰符,则该属性默认属于实例属性

    访问器

    get和set模型

    静态属性

    属于类本身的属性,只能通过类名访问

    接口类

    不可被实例化,只能被继承

    构造函数

    用new关键字创建实例的时候,自动执行的初始化函数

    枚举

    数字型枚举

    初始为数字的枚举类型,默认从0开始,可以指定为任意数字,如果未指定,则沿用上一个常量+1

    字符串型枚举

    不再拥有自动加一的特性,必须指定每一个枚举值

    混合类型

    同时拥有字符串和数字的混合类型,不建议使用

    计算成员和常量成员

    以下情况符合其一就是常量成员

    • 第一个成员没有初始值,默认是0
    • 没有初始值,且前一个成员为数字型常量
    • 字面量和部分数学符号组成的表达式,如:-1, '123'.length, 1 << 1等

    联合枚举和枚举成员类型

    • 联合枚举:枚举类型拥有有限个成员,这些成员组成了类型的并集,在一些条件判断的时候,编译器可以去识别这些类型,如果条件为恒真或者恒假,则会提示错误,例:
    enum E {
      Foo,
      Bar,
    }
    
    function f(x: E) {
      if (x !== E.Foo || x !== E.Bar) {
      // This condition will always return 'true' since the types 'E.Foo' and 'E.Bar' have no overlap.
        //
      }
    }
    
    • 枚举成员类型:针对枚举类型的常量成员,也是一种独立的类型,例:
    enum ShapeKind {
      Circle,
      Square,
    }
    
    interface Circle {
      kind: ShapeKind.Circle;
      radius: number;
    }
    
    interface Square {
      kind: ShapeKind.Square;
      sideLength: number;
    }
    
    let c: Circle = {
      kind: ShapeKind.Square,
      // Type 'ShapeKind.Square' is not assignable to type 'ShapeKind.Circle'.
      radius: 100,
    };
    

    枚举运行时

    在运行时,枚举类型是真实存在的,可以打印出对应的值

    枚举编译时

    运行时,枚举类型虽然存在,但对应的key的字符串却可能跟你预期的不一样,编译时可以用 keyof typeof 关键词来获取key的联合类型,例:

    enum LogLevel {
      ERROR,
      WARN,
      INFO,
      DEBUG,
    }
    
    /**
     * This is equivalent to:
     * type LogLevelStrings = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
     */
    type LogLevelStrings = keyof typeof LogLevel;
    

    反向映射

    数字型枚举类型,可以根据数字获取到key的字符串,例:

    enum Enum {
      A,
    }
    
    let a = Enum.A;
    let nameOfA = Enum[a]; // "A"
    

    常量枚举

    在枚举关键词之前使用 const 关键词,可以避免编译产生额外的代码和反向映射,项目中推荐使用

    环境枚举

    用来定义已存在的枚举类型,不会编译成代码,在枚举类型前使用 declare 关键词,例:

    declare enum Enum {
      A = 1,
      B,
      C = 2,
    }
    

    泛型

    为了提高代码复用率,泛型可以允许指定类型参数,来创建逻辑相同的代码片段(类型,类,函数),例:

    function identity<T>(arg: T): T {
      return arg;
    }
    let output = identity<string>("myString");
    

    泛型类型变量

    上面的示例,arg的参数类型是不确定的,如果要使用数组类型的length属性,需要使用泛型数组类型,例:

    function identity<T>(arg: Array<T>): Array<T> {
      console.log(arg.length)
      return arg;
    }
    

    泛型类型

    上面的示例,要利用泛型函数来创建一个新的函数,可以用以下代码:

    let myIdentify: <T>(arg: T) => T = identify
    

    这里T只是一个标识符,也可以用其他任意字符替代

    我们也可以用调用签名的方式去写(对象字面量类型):

    let myIdentify: {<T>(arg: T): T} = identify
    

    初看之下可能比较复杂,但实际上就是一个对象的key,value的键值对,key表示输入,value表示输出

    因此衍生出使用泛型接口来重写上面的代码,将调用签名抽离成一个函数类型的接口:

    interface GenericIdentityFn {
      <T>(arg: T): T;
    }
    
    function identity<T>(arg: T): T {
      return arg;
    }
    let myIdentity: GenericIdentityFn = identity;
    

    然后可以将泛型参数转移到整个接口上,这样所有成员函数都可以使用这个泛型参数:

    interface GenericIdentityFn<T> {
      (arg: T): T;
    }
    
    function identity<T>(arg: T): T {
      return arg;
    }
    
    let myIdentity: GenericIdentityFn<number> = identity;
    

    泛型接口的使用看具体业务情况

    泛型类

    就是在类的基础上扩展了泛型参数,唯一需要注意的是,静态成员无法使用泛型参数

    class GenericNumber<T> {
      zeroValue: T;
      add: (x: T, y: T) => T;
    }
    let myGenericNumber = new GenericNumber<number>();
    

    泛型约束

    泛型参数一般是类似any的存在,如果需要使用它的一些属性,比如length,则需要额外定义,可以使用Array,或者也可以使用继承的方式,创建一个接口,指定属性来约束泛型参数,例:

    interface Lengthwise {
      length: number;
    }
    
    function loggingIdentity<T extends Lengthwise>(arg: T): T {
      console.log(arg.length); // Now we know it has a .length property, so no more error
      return arg;
    }
    

    :这样一来,函数传参必然是一个包含length属性的对象,就不能是任意值了

    泛型中使用类

    当使用泛型在ts中创建工厂时,则有必要引用类的构造函数,例:

    function create<T>(c: { new (): T }): T {
      return new c();
    }
    

    以下是具体示例:

    class BeeKeeper {
      hasMask: boolean;
    }
    
    class ZooKeeper {
      nametag: string;
    }
    
    class Animal {
      numLegs: number;
    }
    
    class Bee extends Animal {
      keeper: BeeKeeper;
    }
    
    class Lion extends Animal {
      keeper: ZooKeeper;
    }
    
    function createInstance<A extends Animal>(c: new () => A): A {
      return new c();
    }
    
    createInstance(Lion).keeper.nametag;
    createInstance(Bee).keeper.hasMask;
    

    参考

    www.typescriptlang.org/docs/handbo…


    起源地下载网 » TypeScript使用指南(初级篇)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元