跳到主要内容

TS 中 Declare 的作用

· 阅读需 5 分钟

在很多项目里可以看到 *.d.ts 这样的文件,在这里面有时会有很多 declare 出现。它的作用是,声明一个模块、变量、类型...

有时候,一些库不提供类型声明,使用它的时候就会很迷茫,没有代码提示。有时候,使用某个SDK,如果不去声明一下它,会报错说 “找不到名称xxx” ,这时候就需要我们自己去声明一下它。

可以直接在使用它的ts文件里声明,也可以在 *.d.ts 里进行全局范围的声明。

声明名称空间(模块)

某个公司实现了一个库,叫 BOS3D,项目中要使用这个库,且已经把他挂到了 window 对象上,我们在项目里可以直接使用 BOS3D.Version 或者 new BOS3D.Viewer(),但是在TS写的项目中,会提示找不到名称BOS3D,这时候需要自己简要地声明一下这个东西。

declare namespace BOS3D {
var MODE: 'prod' | 'dev' | 'test';
const Version = 4;

class Viewer {
constructor();
}
}

new BOS3D.Viewer(); // 可以使用了
BOS3D.Version; // 4

经过简单的声明之后,就不报错了,也有简单的提示了。

声明变量

使用 declare 来声明变量,可以用 var, const, let 关键字来完成声明。如果想要定义只读的变量,就用 const。如果想要变量是块级作用域,就用 let。

declare var age: number;
declare const year: number;
declare let month: number;

声明带属性的对象

假如有一个 myLib 全局变量,里面有一个 makeGreeting 函数,和一个 numberOfGreetings 属性来储存问候次数。应该这样来定义声明文件。

declare namespace myLib {
function makeGreeting(s: string): string;
let numberOfGreetings: number;
}

重载函数签名

这种场景,在编译器不知道函数定义在哪里时,告诉编译器该函数是怎样定义的类型签名,而不是在自己实现函数签名重载时使用。

正确用法:

// 使用了某些未知库,找不到函数定义,没有代码提示;这样来自己定义一下,方便开发;
declare function getPerson(s: string): object;
declare function getPerson(n: number): object;

错误用法:

declare function getPerson(s: string): object;
declare function getPerson(n: number): object;
function getPerson(arg: string | number): object {
// ...
}

如果自己实现函数签名重载,直接 function 连串下来。不用 declare,它的作用只是告诉编译器东西是怎么定义的,和实现毫无关系。

声明类

使用 declare class 来描述一个类,或者一个 似类 的对象,类可以定义属性或者方法,也包括构造器。

declare class Greeter {
constructor(greeting: string);
greeting: string;
showGreeting(): void;
}

const myGreeter = new Greeter("hello, world");
myGreeter.greeting = "howdy";
myGreeter.showGreeting();

class SpecialGreeter extends Greeter {
constructor() {
super("Very special greetings");
}
}

这是定义类型!!不是实现,运行肯定会报错!只是方便开发过程中有代码提示。

组织类型

用名称空间 namespace 把类型给组织起来,更规范管理类型。

declare namespace GreetingLib {
interface LogOptions {
verbose?: boolean;
}
interface AlertOptions {
modal: boolean;
title?: string;
color?: string;
}
}

// 可以嵌套定义名称空间,也可以这样通过 xxx.xx 定义内嵌的名称空间
declare namespace GreetingLib.Options {
interface Log {
verbose?: boolean;
}
interface Alert {
modal: boolean;
title?: string;
color?: string;
}
}

function exportLog(arg: GreetingLib.Options.Log) {
//...
}