8

I'm trying to use the @types/googlemaps type definition file.

The code looks like

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;
        ...

When I try to use this type definition in my project, like so

import * as google from 'googlemaps';

I get a compile error saying

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

Why does it not consider this types definition file to be a module? Am I using it wrong ? Is the definition file wrong?

CodyBugstein
  • 21,984
  • 61
  • 207
  • 363
  • 3
    https://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html it must be global declarations instead of module.. try using `google.maps.Map`.. if that doesnt work try puting `/// ` on top of your file – Suraj Rao Dec 15 '17 at 08:04
  • I am also facing this problem when trying to use the types defined at @types/jest for typing the testdouble-jest library. I tried adding the /// directive as well as all manner of importing in a definition file (testdouble-jest.d.ts), but it seems to always resolve to any. any thoughts how I can proceed? – osdiab May 03 '19 at 00:19
  • Added more details in a separate question: https://stackoverflow.com/questions/55961831/refer-to-global-declared-namespace-type-in-custom-definition – osdiab May 03 '19 at 00:26

1 Answers1

3

Why does it not consider this types definition file to be a module?

The compiler does not consider this type definition file to be an ECMA6 module because the file lacks a top-level export/import. Instead, the file nests/hides its exports inside a namespace and does not export the namespace. As a result, the namespace becomes part of the global scope, and the file does not become a module.

A file is a module only if it has a top-level import or export. In the following code, both foo.ts and bar.ts are modules, but baz.ts is not, because it lacks a top-level import or export statement.

// 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)

Am I using it wrong?

Yes. You are treating the file like it is a module - which it is not. The alternative is to access its members through the global namespace it defines. Here are two approaches:

One is to 'dot into' the namespace like this:

const div1 = new HTMLDivElement();
const map1 = new google.maps.Map(div1);

Another is to use destructuring like this:

const { Map } = google.maps;
const div2 = new HTMLDivElement();
const map2 = new Map(div2);

Is the definition file wrong?

No. It is taking a valid approach albeit one that is arguably more conventional for a browser (e.g. Firefox) application than it is for a NodeJS application.

See also:

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

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

Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467