How I fixed some trouble importing types in .d.ts files

By

Augment Astro's global App namespace from env.d.ts while importing TypeScript types with import type and declare global.

~~~

I had some trouble making something work in my Astro site.

I used Astro locals and I had to type a variable I shared using locals.

So I went and added that to the src/env.d.ts, as the docs say.

But my types weren’t picked up.

My code looked like this:

/// <reference types="astro/client" />
import { sometype } from 'somelib'

declare namespace App {
  interface Locals {
    somevariable: sometype
  }
}

Imports are allowed in .d.ts files. The important detail is that a top-level import turns the declaration file into a module. A namespace written at the top level is then no longer a global augmentation.

Keep the type import and wrap the namespace in declare global:

/// <reference types="astro/client" />

import type { SomeType } from 'somelib'

declare global {
  namespace App {
    interface Locals {
      somevariable: SomeType
    }
  }
}

export {}

import type is erased from the emitted JavaScript, while declare global makes the intent explicit.

An inline import type also works when you prefer to keep the file as a global script:

declare namespace App {
  interface Locals {
    somevariable: import('somelib').SomeType
  }
}
~~~

Related posts about typescript: