I have a declaration file in my TypeScript project like so:
// myapp.d.ts declare namespace MyApp { interface MyThing { prop1: string prop2: number } }
This works great and I can use this namespace anywhere in my project without having to import it.
I now need to import a type from a 3rd party module and use it in my ambient declaration:
// myapp.d.ts import {SomeType} from 'module' declare namespace MyApp { interface MyThing { prop1: string prop2: number prop3: SomeType } }
The compiler now complains that it can't find namespace 'MyApp', presumably because the import prevents it from being ambient.
Is there some easy way to retain the ambient-ness of the declaration whilst utilising 3rd-party types?
Ambient declarations are a way of telling the TypeScript compiler that the actual source code exists elsewhere. When you are consuming a bunch of third party js libraries like jquery/angularjs/nodejs you can't rewrite it in TypeScript.
Ambient modules is a TypeScript feature that allows importing libraries written in JavaScript and using them seamlessly and safely as if they were written in TypeScript. An ambient declaration file is a file that describes the module's type but doesn't contain its implementation.
Use import myFunction from "./myModule" to bring it in. More commonly, TypeScript modules say export myFunction in which case myFunction will be one of the properties on the exported object. Use import { myFunction } from "./myModule" to bring it in.
Yes, there is a way. It has become easier in TypeScript 2.9 by using import() a type but it's also possible in earlier versions of TypeScript.
The following file is a script. Things declared in a script are added to the global scope. This is why you can use MyApp.MyThing
without importing it.
// myapp.d.ts declare namespace MyApp { interface MyThing { prop1: string; prop2: number; } }
Scripts are limited in that they cannot import anything; when you add an import
, the script becomes a module. I think it's weird to say the least, but it is what it is. What matters is that things defined in a module are scoped to that module, and are not added to the global scope.
However, modules can add declarations to the global scope too, by putting them inside global
:
// myapp.d.ts import {SomeType} from 'module'; declare global { namespace MyApp { interface MyThing { prop1: string; prop2: number; prop3: SomeType; } } }
This file is a module, but it adds a declaration of MyApp.MyThing
to the global scope, so you can still use MyApp.MyThing
in other TypeScript code without importing it.
Note that using the .d.ts
extension has nothing to do with you being able to access the interface without importing it. Both of the above files could have been .ts
files and would still behave exactly the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With