declare关键字的含义是什么?
declare
type Callback = (err: Error | String, data: Array<CalledBackData>) => void;
vs。
declare type Callback = (err: Error | String, data:Array<CalledBackData>) => void;
在TS中找不到解释declare关键字目的的文档。Qué significance ?
这里有一个真实的例子。
我有一个使用Webpack热中间件的TypeScript React应用程序。Webpack热中间件不是用TypeScript编写的,而是用老式的JavaScript编写的。所以它没有TypeScript编译器可以检查的类型声明。
当我运行我的代码时,Webpack热中间件中的对象module存在,我可以console.log它,尽管它是隐藏在我漂亮的新TypeScript React应用程序中的老式JavaScript。
module
module对象也有键,比如module.hot,键可以有值。但是TypeScript设计时编译器(至少在VSCode中)在它下面画了一个红色的曲线,写着property 'hot' does not exist。但它确实存在!
module.hot
property 'hot' does not exist
为了让TypeScript编译器同意,像这样声明它:
declare let module: any
现有的module对象,现在有一个类型any,这让TypeScript编译器高兴了,红色曲线消失了,现在我可以继续编译并编写其他代码。
any
如果你删除关键字declare,只写let module: any,它不会编译,而是说'module' already exists。这就是“环境”;在公认的回答方式。
let module: any
'module' already exists
当您导入一些没有声明类型文件的库时,如*.d.ts,使用Delcare关键字
之后vs eslint不检查语法和上下文,会让你通过,如果你默认使用TSC编译器,那就有很好的理由声明删除语法错误
博士TL;
declare是用来告诉编译器“这个东西(通常是一个变量)已经存在,因此可以被其他代码引用,也没有必要将此语句编译成任何javascript”。
常用用例:
你将网页的引用添加到一个JavaScript文件中,而编译器对此一无所知。也许它是来自其他域的脚本,如“foo.com”。当被求值时,脚本将创建一个带有一些有用API方法的对象,并将其分配给全局作用域中的标识符'fooSdk'。
你希望你的TypeScript代码能够调用fooSdk.doSomething(),但是由于你的编译器不知道fooSdk变量的存在,你会得到一个编译错误。
fooSdk.doSomething()
fooSdk
然后使用declare关键字告诉编译器“相信我,这个变量存在并且具有这种类型”。编译器将使用此语句静态检查其他代码,但不会将其转编译为输出中的任何JavaScript。
declare const fooSdk = { doSomething: () => boolean }
较新的Typescript版本需要稍微不同的语法:
declare const fooSdk : { doSomething: () => boolean }
同样,您可以向类属性添加declare关键字,以告诉编译器不要发出任何会创建此属性的代码,假设您有自己的代码会创建编译器不知道或不理解的属性。
您的具体示例有所不同,因为您声明的是类型,而不是变量,类型已经不会编译到任何JavaScript中。我不知道是否有任何理由声明一个类型。
来自Typescript文档:
Typescript - Working with Other JavaScript Libraries
为了描述不是用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编写的库的形状,我们需要声明该库公开的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; }; } // (...) }
你可以在编写任何实现代码之前使用declare告诉编译器类型,TypeScript会很高兴。
declare function foo(name: string): string
考虑这个场景:您有一个Typescript项目。然后,不管出于什么原因,你决定用JavaScript编写一个模块,并在Typescript代码中使用它。
// getMyName.js module.exports = function getMyName(name) { return name; }
然后将它导入typescript代码中
// myCode.ts import getMyName from 'getMyName'; //getMyName is a JS module not typescript
当导入该JS模块时(allowJs编译器选项应该设置为false,否则JS文件将在没有任何类型定义的情况下被解析),Typescript的编译器会抱怨该模块根本不是模块!
allowJs
false
Could not find a declaration file for module '/absolute/path/to/getMyName.ts'
这是因为Typescript不会自行解析为JS代码。为了避免这个问题,我们应该为JS模块提供类型定义(filename.d.ts)。为此,你可以使用declare和export。
filename.d.ts
export
// getMyName.d.ts declare function getMyName(name: string): string; export default getMyName;
之后,当我们导入JS模块时,typescript不会抱怨任何事情,因为它现在可以访问类型了。