在TypeScript中,由于模块声明文件保存在.d.ts文件中,而且文件中不能有值,因此声明模块类型时要使用declare关键字声明模块中导出的指定类型的值。
TypeScript声明及相应的类型声明
.ts | .d.ts |
---|---|
var a = 1 | declare var a: number |
let a = 1 | declare let a: number |
const a = 1 | declare const a: 1 |
function a(b) { return b.toFiexed() } | declare function a(b: number): string |
class A { b() { return 3 }} | declare class A { b(): number } |
namespace A {} | declare namespace A {} |
type A = number | type A = number |
interface A { b?: string } | interface A { b?: string } |
导出的类型
导出的方式不同,例如全局导出、ES2015导出或CommonJS导出,编写声明文件的方式也不同。
全局导出
如果在一个模块中只为全局命名空间赋值,而没有导出任何代码,只需创建一个脚本模式文件,在变量、函数和类声明前面加上declare(其他声明:例如enum、type等,保持不变):
// 全局变量
declare let someGlobal: GlobalType
// 全局类
declare class GlobalClass {}
// 全局函数
declare function globalFunction(): string
// 全局枚举
enum GlobalEnum (A, B, C)
// 全局命名空间
namespace GlobalNamespace {}
// 全局类型声明
type GlobalType = number;
// 全局接口
interface GlobalInterface {}
这些声明在项目中的任何文件里都可以使用,无须显示导入。比如说,在项目中的任何文件都可以使用someGlobal,无须事先导入,不过在运行时,someGlobal要赋值给全局命名空间(浏览器中的window, NodeJS中的global)。
注意:为了保证文件在脚本模式下,在声明文件中不能使用import和export。
ES2015导出
如果模块使用ES2015导出方式,即使用export关键字,把declare(申明定义了全局变量)替换为export(申明导出了ES2015绑定)即可:
// 默认导出
declare let defaultExport: SomeType
export default defaultExport
// 具名导出
export class SomeExport {
a: SomeOtherType
}
// 类导出
export class ExportedClass {}
// 函数导出
export function exportedFunction(): string
// 枚举导出
enum ExportedEnum {A, B, C}
// 命名空间导出
export namespace SomeNamespace {
let someNamespacedExport: number
}
// 类型导出
export type SomeType = {
a: number
}
// 接口导出
export interface SomeOtherType {
b: string
}
CommonJS导出
在ES2015之前,CommonJS是模块的标准,也是NodeJS的模块标准。CommonJS模块也使用export关键字导出代码,但是语法稍有不同:
declare let defaultExport: SomeType
export = defaultExport
注意:这里是把要导出的代码赋值给export,而不是把export用作修饰符。
第三方CommonJS模块的类型声明中只能有一个导出语句。如想导出多个模块,要利用声明合并行为。
例如,若想为多个导出声明类型,而且没有默认导出,可以导出一个命名空间:
declare namespace MyNamedExports {
export let someExport: SomeType
export type SomeType = number
export class OtherExport {
otherType: string
}
}
export = MyNamedExports
如果CommonJS模块中既有默认导出也有具名导出,这时就要利用声明合并行为了:
declare namespace MyExports {
export let someExport: SomeType
export type SomeType = number
}
declare function MyExports(a: number): string
export = MyExports
UMD导出
为UMD模块提供类型信息的方式基本上与ES2015模块一样。唯一的区别是,如果想让模块在脚本模式下的文件中全局可用,要使用特殊的 export as namespace句法。例如:
// 默认导出
declare let defaultExport: SomeType
export default defaultExport
// 具名导出
export class SomeExport {
a: SomeType
}
// 类型导出
export type SomeType = {
a: number
}
export as namespace MyModule
注意最后一行。有了这一行,项目中处于脚本模式下的文件可以在全局命名空间MyModule上直接使用该模块(无须事先导入)
let a = new MyModule.SomeExport