In the world of TypeScript, modules play a crucial role in organizing and reusing code. TypeScript supports various module systems like CommonJS, AMD, UMD, and ES Modules. However, sometimes you might need to work with libraries that are written in JavaScript or other languages without type definitions. TypeScript provides a way to handle such scenarios through ambient modules.
Ambient modules allow you to declare the shape of a library that is not written in TypeScript. This enables TypeScript to understand how to interact with these libraries, providing type safety and autocompletion support within your code editor.
When you work with JavaScript libraries that do not have TypeScript definitions, TypeScript cannot infer types from them. Ambient modules help by declaring the structure of these libraries so that TypeScript can recognize their APIs.
An ambient module is declared using the declare keyword followed by the module name in quotes. Inside the module declaration, you define the interfaces, classes, functions, and variables provided by the library.
Let's say you have a JavaScript library named simple-library.js that exports a function called greet. You can declare this library as an ambient module like this:
1// simple-library.d.ts2declare module 'simple-library' {3export function greet(name: string): string;4}
Now, you can use the greet function in your TypeScript code with type safety:
1import { greet } from 'simple-library';23const message = greet('World');4console.log(message); // Output: Hello, World!
Consider a more complex library that exports multiple functions and classes. You can declare this library as follows:
1// complex-library.d.ts2declare module 'complex-library' {3export function add(a: number, b: number): number;4export class Calculator {5constructor();6multiply(x: number, y: number): number;7}8}
You can now use the add function and Calculator class in your TypeScript code:
1import { add, Calculator } from 'complex-library';23const sum = add(5, 3);4console.log(sum); // Output: 856const calc = new Calculator();7const product = calc.multiply(4, 2);8console.log(product); // Output: 8
Sometimes, libraries attach themselves to the global scope. For example, a library might add a myLib object to the window object in the browser. You can declare such a library like this:
1// my-global-library.d.ts2declare global {3interface Window {4myLib: {5version: string;6sayHello(name: string): void;7};8}9}1011export {};
Now, you can use the myLib object in your TypeScript code:
1if (window.myLib) {2window.myLib.sayHello('TypeScript');3console.log(window.myLib.version); // Output: 1.04}
In the next section, we will explore Decorators in TypeScript, which provide a way to add metadata and behavior to class declarations and members.
By understanding ambient modules, you can effectively work with JavaScript libraries in your TypeScript projects, ensuring type safety and enhancing your development experience.