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

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 1:[1]

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.

Workaround

So what can be done with the current TypeScript capabilities? To support new file types, you will need a file loader such as Webpack. The logical thing to do would be to add a reference to the file type declaration in the file loader itself. This way, as soon as you configure your file loader to be able to import the file, you will inherit the type:

  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 file loader (e.g. loader/index.d.ts: /// <reference types="../txt" />\r\n - this will link the declaration file back into your package. Note that you can add this reference to any file of your package.

This workaround will only work once you import the file referencing back to the declaration - this is the only way TypeScript can be made aware that this type exists (see https://github.com/microsoft/TypeScript/issues/49124).

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

Solution 2:[2]

to bundle global types, do the following. form typescript

  • specify default typings directory at typeRoots. .e.g "typeRoots": ["./src/types"].
  • create a file /src/types/global.d.ts in the specified directory
  • declare your types in the file inside declare global {} and make sure to have export {} if you don't already export anything.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2