TS 中 Declare 的作用
在很多项目里可以看到 *.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) {
//...
}