Skip to content

Interoperability

TypeScript’s type system is optional and gradual.

This means you can mix JS and TS freely—as long as you understand how TypeScript interprets JavaScript modules and how to provide missing types.

Let’s break it down.


Importing JavaScript into TypeScript

TypeScript can import .js files directly, as long as allowJs is enabled in tsconfig.json:

{
  "compilerOptions": {
    "allowJs": true
  }
}

Example: Importing a JS module

utils.js

export function add(a, b) {
  return a + b
}

index.ts

import { add } from "./utils.js"

add(1, 2) // works

How TypeScript types JS imports

  • If checkJs is off, TS treats JS as any
  • If checkJs is on, TS infers types from the JS code
  • If JSDoc is present, TS uses those types

This gives you multiple migration paths.


Typing Untyped Libraries

Some npm packages don’t ship with TypeScript types.

When you import them, TypeScript will treat them as any:

import foo from "foo" // foo: any

This removes type safety.

There are three ways to fix this:


1. Install community types (@types/...)

Many libraries have type definitions on DefinitelyTyped.

npm install --save-dev @types/lodash

After installing:

import _ from "lodash" // fully typed

This is the easiest and most common solution.


2. Write your own .d.ts file

If no types exist, you can create them.

Create a file:

types/foo/index.d.ts

Inside:

declare module "foo" {
  export function greet(name: string): string
}

Now TypeScript knows how to type the library.

Usage

import { greet } from "foo"

greet("Alice") // typed!

3. Use declare module for quick fixes

If you just want to silence errors temporarily:

declare module "foo"

This tells TypeScript:

“This module exists, but I don’t know its types.”

Everything becomes any.

Use this only as a temporary measure.


Writing Declaration Files (.d.ts)

Declaration files describe the shape of code without implementing it.

They contain:

  • declare statements
  • interfaces
  • function signatures
  • module declarations
  • type aliases

They do not contain runtime code.


Example: Declaring a function

// math.d.ts
declare function add(a: number, b: number): number

Example: Declaring a module

// my-lib.d.ts
declare module "my-lib" {
  export function parse(input: string): number
}

Example: Declaring a class

declare class Person {
  constructor(name: string)
  greet(): string
}

Example: Declaring a global variable

declare const VERSION: string

Where to Put Declaration Files

You have two options:


1. Inside a types/ folder

project/
  src/
  types/
    foo/
      index.d.ts

Add to tsconfig.json:

{
  "compilerOptions": {
    "typeRoots": ["./types", "./node_modules/@types"]
  }
}

2. Inline next to the JS file

utils.js
utils.d.ts

TypeScript automatically picks it up.


JSDoc vs .d.ts

Approach Best For
JSDoc Gradual migration, typing JS files directly
.d.ts files Typing external libraries, providing ambient types
TypeScript files Full migration, maximum safety

You can mix all three in the same project.


Putting It All Together

Here’s a realistic scenario:

You have a JS library:

logger.js

exports.log = function (msg) {
  console.log("LOG:", msg)
}

TypeScript complains:

Could not find a declaration file for module './logger'

Fix: Add a declaration file

logger.d.ts

export function log(msg: string): void

Now in TypeScript:

import { log } from "./logger.js"

log("Hello") // fully typed

This is exactly how you integrate legacy JS into modern TS codebases.


Summary

In this lesson, you learned how TypeScript interoperates with JavaScript:

1. Importing JS into TS

  • Works automatically with allowJs
  • TypeScript infers types or uses JSDoc

2. Typing untyped libraries

  • Install @types/...
  • Write your own .d.ts files
  • Use declare module as a temporary fallback

3. Writing declaration files

  • Describe modules, functions, classes, globals
  • No runtime code
  • Essential for integrating JS libraries

Interoperability is one of TypeScript’s greatest strengths—it lets you adopt TS at your own pace while still working with the entire JavaScript ecosystem.