美文网首页
typescript两种声明文件的区别

typescript两种声明文件的区别

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

    Typescript声明文件写法

    Typescript的声明文件是一个.d.ts为后缀的Typescript代码文件,作用是描述一个Javascript模块内所有导出接口的类型信息。

    Typescript的DefinitelyTyped 声明文件有两种写法:

    • 全局类型声明(Global Type Definition)
    • 模块导出声明(External Module Definition)

    两种声明区别及意义

    我们知道npm包有内建的TS声明文件,从而免去使用typings工具安装TS声明文件的操作。

    1. 既然可以有内建声明文件,为何还需额外安装呢?

    因为不是所有人都在使用Typescript,很多npm包都是纯Javascript编写,作者没太大可能性为其编写模块声明文件,而且内建的声明文件有一定约束。

    1. 什么时候使用全局类型声明?什么时候使用导出类型声明?
    • 需要将新名称引入全局命名空间,就使用全局声明
    • 无需将新名称引入全局命名空间,就使用模块导出声明
    1. 两者有什么区别?

    主要区别在于,npm包里面的内建声明必须使用模块导出声明写法,否则Typescript编译无法通过。

    举例说明

    export function abc(s: string): string {
        return s.substr(0, 4);
    }
    

    其声明文件写法:

    • 模块导出声明写法
    declare interface Iabc {
        (s: string): string
    }
    export declare let abc: Iabc;
    
    • 全局类型声明写法
    declare module "Iabc" {
        iterface abc {
            (s: string): string
        }
        export let abc: Iabc;
    }
    

    模块导出声明写法中,单从文件内容看,无法得知这些内容属于哪个模块,所以必须将之与模块放在一起,作为内建声明文件,Typescript编辑才能得知其所属模块(或放进typings的external目录)。

    全局类型声明写法中,实际是将模块Iabc引入全局空间,即告诉Typescript编辑器,存在一个叫Iabc的模块,想使用就import吧!

    因为任何一个 Node.js 的模块都是必须依靠 require 加载的才能通过字段引用的方式 使用里面的名称,即

    一个模块无法真正地将任何名称引入全局的命名空间中,所以不应该也不能在一个模块的内建声明文件里使用全局声明写法

    如果你的Typescript文件是通过<scipt>标签加载,那么变量、函数等都会被引入到全局命名空间中,这时就要为这个文件写一份全局类型声明了。

    例如:

    // 定义一个全局变量,整个页面都可见
    let startTime: Date = new Date();
    

    需要为之写一份.d.ts文件,供其ts文件引用:

    // 这里将变量名 startTime 引入了 TypeScript 的全局命名空间中。
    declare let startTime: Date;
    

    除此之外,你可以用一个全局类型声明文件定义多个模块、命名空间。

    // node.d.ts
    
    declare namespace NodeJS {
    
        export interface Error {
    
            "name": string;
        }
    }
    
    declare module "http" {
    
        // Node built-in module http
    }
    
    declare module "fs" {
    
        // Node built-in module fs
    }
    

    或者深层模块声明:

    declare module "sample/lib1" {
    
        export let name: number;
    }
    
    declare module "sample/lib2" {
    
        export let value: number;
    }
    
    declare module "sample" {
    
        export * from "sample/lib1";
    
        export * from "sample/lib2";
    }
    

    这是模块导出声明写法做不到的。

    综上所述:

    • 全局类型声明里的名称将被引入整个 TypeScript 全局命名空间中,从引用这个 声明文件起就可以自由使用。
    • 模块导出声明里的名称必须通过 import/require 才能使用。

    相关文章

      网友评论

          本文标题:typescript两种声明文件的区别

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