美文网首页
typescript声明文件写法

typescript声明文件写法

作者: 一懒众衫小小小小 | 来源:发表于2020-04-15 11:01 被阅读0次

    引入模块文件

    以这三个文件为例,分别以模块导出声明 (External Module Definition)全局类型声明(Global Type Definition) 两种写法编写 Definition。

    入口文件引用模块:

    // file: index.js
    var sample = require("sample");
    var lib1 = require("sample/lib1");
    var lib2 = require("sample/lib2");
    

    假设以下为三个文件代码,后面以这三个文件基础编写Definition:

    // file: ./node_modules/sample/index.js
    var abc = 321;
    exports.setABC = function(abcValue) {
    abc = abcValue;
    };
    exports.getABC = function() {
    return abc;
    };
     
    exports.defaultABC = abc;
    
    // file: ./node_modules/sample/lib1.js
    var Hello = (
        function () {
            function Hello(a) {
            this.valueA = a;
        }
    
        Object.defineProperty(
        Hello.prototype,"a", {
            get: function () {
                return this.valueA;
            },
            enumerable: true,
            configurable: true
        });
        Hello.initClass = function () {
            Hello.initCount = 0;
        };
    
        /* 假设这是一个重载函数,支持多种调用方式 */
        
        Hello.prototype.setup = function (x, b) {
            if (b === void 0) { 
                b = null; 
            }
            return false;
        };
        return Hello;
    }());
    
    exports.Hello = Hello;
    
    // file: ./node_modules/sample/lib2.js
     
    var randStrSeed = "abcdefghijklmnopuvwxyz012345";
     
    function randomString(length) {
        var ret = "";
     
        while (length-- > 0) {
            ret += randStrSeed[Math.floor(Math.random() * randStrSeed.length)];
        }
     
        return ret;
    }
     
    module.exports = randomString;
    

    这是三个典型的模块类型:

    • 第一个导出了变量和函数
    • 第二个导出了一个类
    • 第三个则将一个函数作为一个模块导出

    全局类型声明写法

    假如上面3个文件同属一个模块sample,但它并不是我们自己发布到npm的包,即我们无权为它建Definition,所以我们用全局声明写法。

    如果不是很复杂,我们用一个.d.ts文件就可以了。

    第一个文件是模块入口文件,导出了变量和函数,可以直接当作模块sample:

    declare module "sample" {
     
        // 导出函数 setABC
        export function setABC(abcValue: number): void;
     
        // 导出函数 getABC
        export function getABC(): number;
     
        // 导出变量 defaultABC
        export let defaultABC: number;
    }
    

    第二个文件导出了两个类,可以当作模块"sample/lib1"。
    这个类里面有构造函数,有静态方法,有普通方法,有属性,也有静态属性,还有 getter。

    类有两种声明编写方式:标准式和分离式。
    保准方式:

    declare module "sample/lib1" {
        export class Hello {
            private valueA;
            b: number;
            static initCount: number;
            a: number;
            constructor(a: number);
            static initClass(): void;
            // 假设这是重载函数,支持多种调用方式
            setup(name: string): boolean;
            setup(name: string, age: number): boolean;
        }
    }
    

    但是这种写法也有不便的地方,比如扩展类不方便——JavaScript允许你随时扩展一个类的原型对象实现对类的扩展,或者随时给类添加静态成员。标准式写法很难实现扩展,因为你无法重复声明一个类。

    分离式声明:
    在这之前我们要理解,JS 的类是用函数实现的,即是说 JS 的类本质上就是一个构造函数 + Prototype。Prototype 的成员就是类的成员;而类的静态方法就是这个构造函数对象本身的成员方法。

    declare module "sample/lib1" {
    
        // 在分离式写法里面,一个类的 Prototype 的声明是一个直接以类名称为名的interface。
        // 成员函数和变量/getter/setter 都行写在 prototype的接口里面。
        
        // 注:类原型的interface取名与类一致
        export interface Hello {
        
            // 接口里面只写类的 public 属性
            b: number;
            
            // Getter/Setter 直接成属性即可
            a: number;
            
            // 重载函数的声明写法
            setup(name: string): boolean;
            setup(name: string, age: number): boolean;
        }
        
        // 在分离式写法里面,一个类的构造函数对象也是一个 interface ,但是对
        // 其命名无具体要求,合理即可。
        
        // 把类的静态方法和属性都写在这里面。
        export interface HelloConstructor {
        
            // 静态属性
            initCount: number;
            
            // 静态方法
            initClass: void;
            
            // 构造函数!使用 new 代替 constructor,并声明其返回值类型是该类的Prototype。
            new(a: number): Hello;
        }
        
         // 将 Hello 覆盖声明为HelloConstructor。
            // 这样,在需要作为类使用的时候它就是 HelloConstructor,需要作为接口使用的时候就是 Hello(原型接口)。
        
        export let Hello: HelloConstructot;
    }
    

    第三个文件,直接将一个函数作为模块导出。

    declare module "sample/lib2" {
        let randomString: (length: number) => string;
        
        export = randomString;
    }
    

    最后把 3 个模块的声明合并成一个文件 sample.d.ts,在文件里用三斜线指令引用即可。

    模块导出声明写法

    模块导出声明写法里面不用注明是哪个模块,一般给每个导出的文件都配备一个以 .d.ts 为后缀的 Definition。

    文件 ./node_modules/sample/index.d.ts

    // File: ./node_modules/sample/index.d.ts
    
    // 导出函数 setABC
    export declare function setABC(abcValue: number): void;
    
    // 导出函数 getABC
    export declare function getABC(): number;
     
    // 导出变量 defaultABC
    export declare let defaultABC: number;
    

    文件 ./node_modules/sample/lib1.d.ts

    // File: ./node_modules/sample/lib1.d.ts
     
    export class Hello {
     
        private valueA;
     
        b: number;
     
        static instCount: number;
     
        a: number;
     
        constructor(a: number);
     
        static initClass(): void;
     
        //假设这是一个重载函数,支持多种调用方式
        setup(name: string): boolean;
     
        setup(name: string, age: number): boolean;
    }
    

    文件 ./node_modules/sample/lib2.d.ts

    // File: ./node_modules/sample/lib2.d.ts
     
    let randomString: (length: number) => string;
     
    export = randomString;
    

    编写Definition注意事项

    1. 不要使用内层declare

    只能在 Definition 的顶层使用 declare,比如下面的写法都是错误的:

    declare module "sample" {
        // 此处应当使用 export
        declare let a: string;
    }
     
    declare namespace Sample {
        // 此处应当使用 export
        declare let a: string;
    }
    
    1. 避免全局污染

    虽然全局声明写法允许你引入名称到全局命名空间中,但这也意味着,引入的顶层名称都是全局的。所以应该将所有的模块内导出的元素都放进模块或者命名空间内:

    declare module "sample" {
       //仅可通过 import { Person } from "sample" 访问。
       export interface Person {
           name: string;
       }
    }
    
    declare namespace Sample {
       export interface Animal {
           type: string;
       }
    }
    

    而不是

    // 无需 import 即可使用,即全局的
    interface Person {
       name: string;
    }
    
    1. 注意声明冲突
    2. 模块名称要区分大小写!

    参考文档:https://www.cnblogs.com/dhcn/p/7722248.htm

    相关文章

      网友评论

          本文标题:typescript声明文件写法

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