How to include a global file type declaration in a TypeScript (Node.js) package

Issue

I’m working on a package that I am planning to publish publicly on npmjs. Let’s call it the "text package".

I would like that by default when installing that package, you can import .txt files directly and get the correct type (out of the box), like this:

import text from './file.txt'

The text variable would be of type string because the package would have defined its type, using something like this (in a global.d.ts):

declare module '*.txt' {
    export const text: string;
    export default text;
}

If I include that global.d.ts in my package, and that I import something from this package, then I will automatically get the correct type when importing a .txt file.

But the problem is sometimes I would just need to import a .txt file without importing anything from the "text package", which is why I was wondering if there is some sort of way, as you install a package to install a global type that does not require to import anything else for the type to apply.

In other words, as soon as you install my "txt package" the declare module '*.txt' would apply to my entire project out of the box.

Is there even a way to do this, or whoever installs my package would have to declare their own global type (e.g., declarations.d.ts) to be able to import .txt files globally?

I know that even if the import type works, it will still require Webpack or another bundler to really work but this question is just about the type.

Solution

The short answer is:

TypeScript does not support Global types without importing the file referring to the type.

More details:

One example that I found doing this was Next.js – when creating a TypeScript app using npx create-next-app@latest --typescript you can start importing *.css files (for example) and get the correct type.

Where I got confused is that I originally thought that the type was coming from the next-env.d.ts but even when I deleted the file, *.css import was still working in Visual Studio code. But the reason it was, is because a file in the pages directory were importing Next.js’ index.d.ts file.

Basically, in Visual Studio Code, as soon as your import a type somewhere in your project, if it’s global, it will be accessible everywhere.

Potential workaround

So what can be done with the current TypeScript capabilities? Well, we can always add the file type declaration in the package’s main type file:

  1. create a txt.d.ts in our package’s source directory (e.g. src) – you can use any name for the file, it’s not important
  2. if you are using eslint, add an entry to ignore the type file (e.g. 'src/*.d.ts' in your ignorePatterns option
  3. Since you are adding a d.ts file in your source that is not managed by tsc, you need to add a script that will perform the following actions:
    1. Copy txt.d.ts in the target directory of the compiled files for your package
    2. Add this line at the top of your package’s main type file (e.g. index.d.ts: /// <reference types="./txt" />\r\n – this will link the declaration file back into your package

This workaround will only work if you import the type file of the package.

Another alternative could also be to add manual steps (in a readme file) to add a global type declaration file.

I also have opened a feature request on the TypeScript repo: https://github.com/microsoft/TypeScript/issues/49124

Answered By – Nicolas Bouvrette

Answer Checked By – Jay B. (AngularFixing Admin)

Leave a Reply

Your email address will not be published.