Right, let’s talk about triple-slash directives. No, they’re not a secret handshake or a way to comment out your entire life. They’re a pre-ES6, pre-module-world holdover that the TypeScript team keeps around because, well, sometimes you need an old key for a weird, specific lock. They’re essentially single-line XML comments (/// ) that live at the very top of your file and give instructions to the compiler. The one you’ll actually use in modern projects is almost exclusively <reference types="..." />.

Think of it as a way to shout, “Hey, TypeScript compiler, before you even think about processing this file, go and also grab the types from this other library!” It’s a directive, not an import. This is a crucial distinction. It manipulates the compiler’s understanding of your project’s “ambient” context.

Why Would You Use This Ancient Artifact?

In the modern era of ES modules, you probably don’t need this 99% of the time. You just npm install @types/some-library and then use a regular import or import type statement. The module system handles it all for you.

So when do you use it? Primarily in two scenarios:

  1. For Global Libraries (The Classic Use Case): You’re using a library that attaches itself to the global scope (like jQuery with its $). You can’t import it because it’s not a module; it’s just… there. The triple-slash reference tells TypeScript, “The types for this global thing are over here, trust me.”
  2. In Declaration Files (.d.ts): This is the most legitimate modern use. When you’re writing your own global declaration files, you might need to reference types from another library. Since you’re not in a module context (no import/export), this is how you do it.

Here’s a realistic example. Let’s say you have a legacy script that adds a greet() function to the global window object.

global-greeter.js

// This is some old-school JS you include via <script> tag
window.greet = function(name) {
    return "Hello, " + name;
};

To give TypeScript type information for this, you’d create a declaration file and use a triple-slash reference to pull in DOM types (because window is part of the DOM).

global-greeter.d.ts

/// <reference types="dom" />

declare global {
    interface Window {
        greet(name: string): string;
    }
}

// This line is necessary to make this file a module and thus allow `declare global`.
export {};

Now, in any .ts file in your project, TypeScript will know that window.greet exists and is typed correctly, all without a single import.

The Crucial “How It Works” (Don’t Screw This Up)

The magic behind <reference types="..." /> is infuriatingly simple: it directly corresponds to the name of a package in your node_modules/@types directory. The directive /// <reference types="jquery" /> literally tells the compiler to go find and include the file node_modules/@types/jquery/index.d.ts.

This leads to the most common pitfall: It only works for globally-scoped declaration files. If you stick one of these directives inside a file that contains ES module imports or exports, it’s silently ignored. The compiler thinks, “Oh, you’re using modules? You clearly know what you’re doing, I’ll just let you handle dependencies yourself.” It’s a fantastic way to waste an hour debugging why your types aren’t being picked up. Always use these directives only in global scripts or your own global .d.ts files.

The Modern Alternative (You Should Probably Do This)

For any project that uses a bundler like Webpack or Vite, just use ES modules. Even for types. It’s cleaner, it’s explicit, and it doesn’t rely on magic compiler directives.

Instead of a triple-slash reference in a .ts file, do this:

// Instead of /// <reference types="jquery" />
import type { JQueryStatic } from 'jquery';

// Now you can use the JQueryStatic type, which represents '$'
declare const $: JQueryStatic;

This is unequivocally better. It’s standard JavaScript, it’s clear where the dependency comes from, and it works consistently everywhere. The triple-slash directive is the dusty tool in the back of the shed; import type is the shiny power tool on your workbench. Use the right one for the job, and that job is almost always modern module-based development.