declare
关键字的目的是什么?
type Callback = (err: Error | String, data: Array<CalledBackData>) => void;
与
declare type Callback = (err: Error | String, data:Array<CalledBackData>) => void;
找不到说明declare
TS中关键字目的的文档。
Answers:
这是一个真实的例子。
我有一个使用Webpack Hot Middleware的TypeScript React应用程序。Webpack中间件不是用TypeScript编写的,而是用老式的JavaScript编写的。因此,它没有TypeScript编译器可以检查的类型声明。
当我运行代码时,module
来自Webpack Hot Middleware的对象存在,并且尽管它是隐藏在我新的TypeScript React应用程序中的很好的老式JavaScript,但我可以进行console.log记录。
该module
对象还具有键,例如module.hot
,并且键可以具有值。但是TypeScript设计时编译器(至少在VSCode中)在其下写着一个红色的波浪形property 'hot' does not exist
。但是它确实存在!
为了使TypeScript编译器达成一致,请这样声明:
declare let module: any
现有module
对象现在的类型为any
,这使TypeScript编译器现在感到满意,红色弯弯曲曲地消失了,现在我可以继续编译并编写其他代码了。
如果删除关键字declare
并仅编写let module: any
,它将不会编译,而是说'module' already exists
。这就是被接受的答案中“环境”的含义。
tl; dr
“ declare”用于告诉编译器“此事物(通常是变量)已经存在,因此可以被其他代码引用,也无需将该语句编译为任何JavaScript”
常见用例:
您将对网页的引用添加到编译器一无所知的JavaScript文件中。也许这是一个来自其他域名(例如“ foo.com”)的脚本。经过评估,脚本将创建并使用一些有用的api方法进行对象化,并将其分配给全局范围内的标识符'fooSdk'。
您希望您的TypeScript代码能够调用“ fooSdk.doSomething()”,但由于编译器不知道此变量存在,因此会出现编译错误。
然后,您可以使用声明关键字作为告诉编译器“相信我,此变量存在并且具有这种类型”的方式。编译器将使用此语句来静态检查其他代码,但不会将其反编译为输出中的任何JavaScript。
declare const fooSdk = { doSomething: () => boolean };
同样,您可以在类属性中添加define关键字,以告诉编译器不要发出任何会创建此属性的代码,前提是您拥有自己的代码会创建该属性,而编译器对此并不了解或不理解。
您的特定示例有所不同,因为您声明的是类型,而不是变量,所以类型已经不能编译为任何JavaScript。我不知道是否有任何理由来声明类型。
来自Typescript文档:
为了描述不是用TypeScript编写的库的形状,我们需要声明该库公开的API。因为大多数JavaScript库仅公开一些顶级对象,所以名称空间是表示它们的好方法。
我们将没有定义实现的声明称为“环境”。通常,这些文件在.d.ts文件中定义。如果您熟悉C / C ++,则可以将它们视为.h文件。让我们看几个例子。
环境命名空间
流行的库D3在称为d3的全局对象中定义其功能。由于此库是通过标签(而不是模块加载器)加载的,因此其声明使用名称空间来定义其形状。为了让TypeScript编译器看到这种形状,我们使用环境名称空间声明。例如,我们可以开始编写如下代码:
D3.d.ts(简体摘录)
declare namespace D3 {
export interface Selectors {
select: {
(selector: string): Selection;
(element: EventTarget): Selection;
};
}
// (...)
}
您可以在编写任何实现代码之前使用声明来告诉编译器有关类型的信息,TypeScript会很高兴。
declare function foo(name: string): string
declare
为现有变量指定类型,而不声明新变量。