文档章节

TypeScript 的两种声明文件写法的区别和根本意义

全体人员
 全体人员
发布于 2016/09/15 17:47
字数 1128
阅读 6136
收藏 9

作者: Angus.Fenying <i.am.x.fenying@gmail.com>

日期: 2016-09-15 05:40 PM

我们知道 NPM 包可以有内建的 TS 声明文件,从而免去使用 typings 工具安装 TS 声明文件的操作。那既然可以有内建的声明文件,为何还需要额外安装呢?因为不是 所有人都在使用 TypeScript,很多 NPM 模块都是纯 JavaScript 编写的,其作者 没有太大的可能性为之编写模块声明文件。而且内建的声明文件有一定约束。

TypeScript 的 DefinitelyTyped 声明文件有两种写法,一种叫做 全局类型声明(Global Type Definition),另一个则是叫做 模块导出声明(External Module Definition)

External Module 一词源自 TypeScript 1.5 之前的 内部模块/外部模块 之说,而 1.5 之后内部模块变成了 namespace,外部模块直接化为模块, 不再有内外部模块之说。

所以这里将 External Module Definition 译为 模块导出声明 比较合适。

DefinitelyTyped 对此的说明是:

  • 如果你的模块需要将新的名称引入全局命名空间,那么就应该使用全局声明。
  • 如果你的模块无需将新的名称引入全局命名空间,那么就应该使用模块导出声明。

这两者有什么不同呢?

首先,最主要的区别在于,NPM 模块里面的内建声明文件必须使用模块导出声明写法, 否则 TypeScript 编译无法通过。下面来看一个简单的例子:

以一个名为 abc 的模块为例,TS源代码如下:

export function abc(s: string): string {

    return s.substr(0, 4);
}

其声明文件有两种写法:

  • 第一种,模块导出声明写法

    declare interface funcAbcSign {
        (s: string): string
    }
    
    export declare let abc: funcAbcSign;
    
  • 第二种,全局类型声明写法

    declare module "abc" {
        interface funcAbcSign {
            (s: string): string
        }
    
        export let abc: funcAbcSign;
    }
    

如果要理解两者的区别,首先要理解其意义。模块导出声明写法 中,单从这个文件内容 看来是无法得知这些内容属于哪个模块的。所以必须将之与模块放在一起,作为内建声明文件, TypeScript 编译器才能得知其所属的模块。(或者放进 typings 的 external 目录)

全局类型声明写法 中,实际上是将模块名称 abc 引入了全局空间,即告诉 TypeScript 编译器,存在一个叫 abc 的模块,想使用里面的名称,就 import 吧!

因为任何一个 Node.js 的模块都是必须依靠 require 加载的才能通过字段引用的方式 使用里面的名称,即是说 一个模块无法真正地将任何名称引入全局的命名空间中,所以不应该也不能在一个模块 的内建声明文件里使用全局声明写法!

这样,就明白了什么时候应该使用全局声明写法,什么时候应该使用模块导出声明写法了

如果你写的 TypeScript 文件是在浏览器上通过 <script> 标签加载的,那么里面的 变量、函数等都会被引入到全局命名空间中,这时候就需要为这个文件写一份全局类型声明 了!比如这个文件:

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

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

// 这里将变量名 appStartedTime 引入了 TypeScript 的全局命名空间中。
declare let appStartedTime: 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 才能使用。

© 著作权归作者所有

共有 人打赏支持
全体人员
粉丝 15
博文 12
码字总数 12918
作品 0
深圳
程序员
私信 提问
加载中

评论(1)

T
Txy_2012
赞赞赞赞赞赞
旧项目TypeScript改造问题与解决方案记

概述 由于本次改造的项目为一个通过NPM进行发布的基础服务包,因此本次采用TypeScript进行改造的目标是移除Babel全家桶,减小包体积,同时增加强类型约束从而避免今后开发时可能的问题。 本次...

黄Java
07/25
0
0
Vue with TypeScript

最近尝试了一下 TypeScript,试着把一个 Vue 项目改成了 TypeScript 的,感觉还不错。 目前 Vue 和 TypeScript 的配合还不算很完美,Vuex 和 TypeScript 的配合挺糟糕的,尝试需要谨慎,如果...

凤晴铃玉
10/31
0
0
在 Vue 中使用 TypeScript 的一些思考(实践)

Vue.extend or vue-class-component 使用 TypeScript 写 Vue 组件时,有两种推荐形式: :使用基础 Vue 构造器,创建一个“子类”。此种写法与 Vue 单文件组件标准形式最为接近,唯一不同仅是...

三毛丶
07/09
0
0
TypeScript基础入门之Javascript文件类型检查(三)

转发 TypeScript基础入门之Javascript文件类型检查(三) 继续上篇文章【TypeScript基础入门之Javascript文件类型检查(二)】 支持JSDoc 下面的列表概述了使用JSDoc注释在JavaScript文件中提供类...

durban
10/31
0
0
从 Vue typings 看 “this”

在 2.5.0 版本中,Vue 大大改进了类型声明系统以更好地使用默认的基于对象的 API。 意味着当我们仅是安装 Vue 的声明文件时,一切也都将会按预期进行: ,就是 Vue; 属性上,具有 Methods ...

三毛丶
10/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

浅析微信支付:开通免充值产品功能及如何进行接口升级指引

本文是【浅析微信支付】系列文章的第十五篇,主要讲解如何开通免充值产品功能流程和其中的注意事项,对于接口升级会重要讲解,避免爬坑。 浅析微信支付系列已经更新十五篇了哟~,没有看过的...

YClimb
41分钟前
1
0
看看ArrayDeque源码

之前看了其他实现Deque接口的类,这里再看看ArrayDeque吧,下图可以看到这个类设计的结构层次,其实Deque接口是继承了Queue接口的。用可调整大小的数组实现Deque接口。没有容量限制,他们根据...

woshixin
41分钟前
2
0
如何存储登录cookie,发送一个post类型的api请求?

其实发送post请求和get请求一样,主要就是不知道如何存储登录cookie进行发送请求,请教xx得到如下解决办法 点击右下方的cookies,填写cookies信息,如图 1填写登录的cookie名,2填写cookie的...

七曦777
41分钟前
1
0
利用cefSharp实现网页自动注册登录的需要注册的一些事项

最近朋友有个需要自动注册登录点击的事,我帮着写了写,好久没写过这东西了,在写的过程中总结了需要注意的一些事项。 一、换IP之后要测试一下速度,我目前用的最简单的测试方法就是20-30秒加...

我退而结网
50分钟前
2
0
Go语言中使用 BoltDB数据库

boltdb 是使用Go语言编写的开源的键值对数据库,Github的地址如下: https://github.com/boltdb/bolt boltdb 存储数据时 key 和 value 都要求是字节数据,此处需要使用到 序列化和反序列化。...

Oo若离oO
50分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部