参考阅读:https://timmousk.com/blog/typescript-declare/

简介

declare 关键字用来告诉编译器,某个类型是存在的,可以在当前文件中使用。它的主要作用,就是让当前文件可以使用其他文件声明的类型。举例来说,自己的脚本使用外部库定义的函数,编译器会因为不知道外部函数的类型定义而报错,这时就可以在自己的脚本里面使用 declare 关键字,告诉编译器外部函数的类型。这样的话,编译单个脚本就不会因为使用了外部类型而报错。declare 关键字可以描述以下类型

  • 变量(const、let、var 命令声明)
  • type 或者 interface 命令声明的类型
  • class
  • enum
  • 函数(function)
  • 模块(module)
  • 命名空间(namespace)

declare 关键字的重要特点是,它只是通知编译器某个类型是存在的,不用给出具体实现。比如,只描述函数的类型,不给出函数的实现,如果不使用 declare,这是做不到的。declare 只能用来描述已经存在的变量和数据结构,不能用来声明新的变量和数据结构。另外,所有 declare 语句都不会出现在编译后的文件里面

declare variable

declare 关键字 - 图1

declare function

declare 关键字 - 图2

declare class

declare 关键字 - 图3

declare module | declare namespace

如果想把变量、函数、类组织在一起,可以将 declare 与 module 或 namespace 一起使用。示例中,declare 关键字给出了 module 或 namespace 的类型描述

declare 关键字 - 图4

declare module 和 declare namespace 里面,加不加 export 关键字都可以。示例中,namespace 和 module 里面使用了 export 关键字

declare 关键字 - 图5

下面的例子是当前脚本使用了 myLib 这个外部库,它有方法 makeGreeting() 和属性 numberOfGreetings

declare 关键字 - 图6

declare 关键字的另一个用途,是为外部模块添加属性和方法时,给出新增部分的类型描述。示例中,从模块 moduleA 导入了 Foo 接口,将其重命名为 Bar,并用 declare 关键字为 Bar 增加一个属性 custom

declare 关键字 - 图7

下面是另一个例子。一个项目有多个模块,可以在一个模块中,对另一个模块的接口进行类型扩展。示例中,脚本 a.ts 定义了一个接口A,脚本 b.ts 为这个接口添加了属性y。declare module ‘./a’ {} 表示对 a.ts 里面的模块,进行类型声明,而同名 interface 会自动合并,所以等同于扩展类型

declare 关键字 - 图8

使用这种语法进行模块的类型扩展时,有几点需要注意

  1. declare module NAME 语法里面的模块名 NAME,跟 import 和 export 的模块名规则是一样的,且必须跟当前文件加载该模块的语句写法(上例 import { A } from ‘./a’)保持一致
  2. 不能创建新的顶层类型。也就是说,只能对 a.ts 模块中已经存在的类型进行扩展,不允许增加新的顶层类型,比如新定义一个接口B
  3. 不能对默认的 default 接口进行扩展,只能对 export 命令输出的命名接口进行扩充。这是因为在进行类型扩展时,需要依赖输出的接口名

某些第三方模块,原始作者没有提供接口类型,这时可以在自己的脚本顶部加上下面一行命令。加上下面的命令以后,外部模块即使没有类型声明,也可以通过编译。但是,从该模块输入的所有接口都将为 any 类型

declare 关键字 - 图9

declare module 描述的模块名可以使用通配符。示例中,模块名 my-plugin-* 表示适配所有以 my-plugin- 开头的模块名(比如 my-plugin-logger)

declare 关键字 - 图10

declare global

declare 关键字 - 图11

declare enum

declare 关键字给出 enum 类型描述的例子如下,下面的写法都是允许的

declare 关键字 - 图12

declare module 用于类型声明文件

declare 关键字 - 图13