TS声明文件的语法使用

128 阅读2分钟

declare前缀的作用

  • declare 定义的类型只会用于编译时的检查,编译结果中会被删除。即不会生成实际代码。
  • 如下案例编译结果是:var directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
  declare enum Directions {
      Up,
      Down,
      Left,
      Right
  }
  let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
  • 常量最终会被替换成原始值
  • 编译的结果是:var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
  declare const enum Directions {
      Up,
      Down,
      Left,
      Right
  }
  let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

变量的声明

声明在全局文件或模块文件中的可见性不同

// declare var, let, const 声明变量
declare var jQuery: (selector: string) => any;

// declare function 声明方法法
declare function Fn(selector: string): any;

// declare class 声明类
declare class Animal {}

// declare enum 声明枚举类型 
declare enum Directions {
    Up,
    Down,
}

// declare namespace 声明(含有子属性的)对象
// 模块文件后 namespace已经比较少用, 除非是给第三方包写声明文件
declare namespace NS {
    function ajax(url: string, settings?: any): void;
}

// interface 和 type 声明类型
interface Animal {
}
type NumberString = number | string;

语法的声明合并

  • 函数与"函数、命名空间"可以合并
  • "interface"与"接口,类,函数,命名空间"可以合并
    • “class"同"interface"
    • 合并的属性的类型必须是唯一的
  • 假如 jQuery 既是一个函数,可以直接被调用 jQuery('#foo'),又是一个对象.

模块声明文件

  • 需要export来导出变量,使其外部可见。
  • 并且需要根据不同的模块加载器,编写不同的导出语法。
    • ES6模块加载
      // export 导出变量
      export const name: string;
      // export namespace 导出(含有子属性的)对象
      export namespace foo {
          const name: string;
      }
      // export default ES6 默认导出
      export default function foo(): string;
      
    • commonjs 导出模块
      // 使用 export = 之后,就不能使用ES6语法再单个导出 export { bar }
      export = foo;
      
      declare function foo(): string;
      declare namespace foo {
          const bar: number;
      }
      
    • export as namespace UMD 库声明全局变量
      // 一般使用 export as namespace 时,都是先有了 npm 包的声明文件,再基于它添加一条 export as namespace 语句
      export as namespace foo;
      export = foo;
      
      declare function foo(): string;
      declare namespace foo {
          const bar: number;
      }
      

模块扩展

  • 模块扩展全局变量

      // `declare global {}`是运用在模块声明文件中的,表示对原始的全局类型的增强,随模块的引入引入,随模块的卸载而卸载。
    declare global {
        interface String {
            prependHello(): string;
        }
    }
    
  • 模块扩展模块(模块插件)

    // 扩展原有模块的类型的声明模版
    import * as moment from 'moment';
    
    declare module 'moment' {
        export function foo(): moment.CalendarKey;
    }
    

三斜杠指令语法

  • 全局声明文件中使用模块的类型,但是不能使用import等语法。
    /// <reference types="jquery" />
    declare function foo(options: JQuery.AjaxSettings): string;
    
  • 全局变量的声明文件太大时,可以通过拆分为多个文件,然后在一个入口文件中将它们一一引入,来提高代码的可维护性。比如 jQuery 的声明文件就是这样的:
    /// <reference types="sizzle" />
    /// <reference path="JQueryStatic.d.ts" />
    /// <reference path="JQuery.d.ts" />
    /// <reference path="misc.d.ts" />
    /// <reference path="legacy.d.ts" />
    
    export = jQuery; // namespace jQuery·