如何导入其顶级元素是未导出的命名空间的Typescript类型定义文件?

Cod*_*ein 8 namespaces typescript typescript-definitions

我正在尝试使用@types/googlemaps类型定义文件。

代码看起来像

declare namespace google.maps {
    /***** Map *****/
    export class Map extends MVCObject {
        constructor(mapDiv: Element|null, opts?: MapOptions);
        fitBounds(bounds: LatLngBounds|LatLngBoundsLiteral): void;
        ...
        ...
        overlayMapTypes: MVCArray<MapType>;
    }

    export interface MapOptions {
        backgroundColor?: string;
        disableDoubleClickZoom?: boolean;
        draggable?: boolean;
        ...
Run Code Online (Sandbox Code Playgroud)

当我尝试在项目中使用此类型定义时,就像这样

import * as google from 'googlemaps';
Run Code Online (Sandbox Code Playgroud)

我收到一个编译错误提示

Error:(2, 25) TS2306:File 'C:/Users/CodyB/musicappproj/src/node_modules/@types/googlemaps/index.d.ts' is not a module.
Run Code Online (Sandbox Code Playgroud)

为什么不将这个类型定义文件视为模块?我使用错了吗?定义文件是否错误?

Sha*_*tin 3

为什么它不认为这个类型定义文件是一个模块?

编译器不会将此类型定义文件视为 ECMA6 模块,因为该文件缺少顶级导出/导入。相反,该文件将其导出嵌套/隐藏在 a 内namespace,并且不导出名称空间。结果,命名空间成为全局范围的一部分,并且文件不会成为模块。

仅当文件具有顶级导入或导出时,它才是模块。在下面的代码中, 和foo.ts都是bar.ts模块,但baz.ts不是,因为它缺少顶层importorexport语句。

// foo.ts
console.log('foo');
export {}

// bar.ts
import * as foo from './foo';
console.log('bar');

// baz.ts
console.log('baz');

// index.ts
import * as foo from './foo';
import * as bar from './bar';
import * as baz from './baz'; // File 'c:/dev/temp/baz.ts' is not a module.ts(2306)
Run Code Online (Sandbox Code Playgroud)

难道是我用错了?

是的。您将文件视为一个模块 - 但事实并非如此。另一种方法是通过它定义的全局命名空间来访问其成员。这里有两种方法:

一种是像这样“点入”命名空间:

const div1 = new HTMLDivElement();
const map1 = new google.maps.Map(div1);
Run Code Online (Sandbox Code Playgroud)

另一种是像这样使用解构:

const { Map } = google.maps;
const div2 = new HTMLDivElement();
const map2 = new Map(div2);
Run Code Online (Sandbox Code Playgroud)

是不是定义文件错误?

不。它采用了一种有效的方法,尽管这种方法对于浏览器(例如 Firefox)应用程序来说可能比对于 NodeJS 应用程序来说更为传统。

也可以看看:

https://www.typescriptlang.org/docs/handbook/namespaces.html

https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html