Telokis
Telokis

Reputation: 3389

TypeScript not finding variable declared in type declaration if I import a file

I made a very simple library which contains a .d.ts (source) which has the following structure (I omit the details because the file works fine, it likely is a config issue in my project):

// Some helper types and interfaces

type TranslationFunction = /* ... */;

export { TranslationFunction };

Then, I do npm i -D embed-i18n-webpack-plugin to install the package into my own project and create a file typings/translation.d.ts to declare a global t variable of type TranslationFunction like follow:

import { TranslationFunction } from "embed-i18n-webpack-plugin";

declare const t: TranslationFunction;

Using VSCode, I can hover over t in this file and it tells me that it has the proper type as defined in my original index.d.ts. This means that when I'm in this file, it properly finds it.

In this same typings directory, I have some other files declaring constants but they never import anything and work as expected.

However, when I try to use the global t function inside my code, I get an error stating

Cannot find name 't'. ts(2304)

BUT if I simply comment the import inside my typings/translation.d.ts:

// import { TranslationFunction } from "embed-i18n-webpack-plugin";

declare const t: TranslationFunction;

It works fine but since it doesn't know TranslationFunction, it collapses into any.

Maybe the type declaration file of my package is wrong and should contain some declare module? I'm not really 100% sure of the behavior when it comes to publishing type declarations on npm, I usually use them in plain TS so it works fine. It's the first time I use one inside another type declaration file.

In case it might be relevant, here is my tsconfig.json:

{
    "compilerOptions": {
        "allowJs": true,
        "allowSyntheticDefaultImports": true,
        "jsx": "preserve",
        "lib": ["dom", "es2017"],
        "module": "esnext",
        "moduleResolution": "node",
        "noEmit": true,
        "noUnusedLocals": true,
        "noUnusedParameters": false,
        "noImplicitAny": false,
        "preserveConstEnums": true,
        "removeComments": false,
        "strictFunctionTypes": false,
        "resolveJsonModule": true,
        "skipLibCheck": true,
        "sourceMap": true,
        "strict": true,
        "experimentalDecorators": true,
        "target": "esnext",
        "extendedDiagnostics": true,
        "paths": {
            "$common/*": ["../Common/*"],
            "$config": ["./config"],
            "$game/*": ["./src/game/*"],
            "$containers/*": ["./src/containers/*"],
            "$phaser/*": ["./src/phaser/*"],
            "$network/*": ["./src/network/*"],
            "$pages/*": ["./src/pages/*"],
            "$components/*": ["./src/components/*"],
            "$helpers/*": ["./src/helpers/*"],
            "$rematch/*": ["./src/rematch/*"],
            "$hooks/*": ["./src/hooks/*"],
            "$types/*": ["./src/types/*"],
            "$src/*": ["./src/*"]
        },
        "rootDir": ".",
        "baseUrl": "."
    },
    "exclude": ["**/node_modules/*", "build", "coverage"]
}

Finally, I have tried some things to see if that would solve my issue:

Upvotes: 4

Views: 954

Answers (1)

bryan60
bryan60

Reputation: 29305

importing into declaration files and making them globally available is a little weird, looks like this:

declare const t: import("embed-i18n-webpack-plugin").TranslationFunction;

That should be all you need to do to. Typescript won't register a declaration as global if it has traditional imports in it, so you need to use this import style. this does require typescript version >= 2.9

docs on it: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#import-types

Upvotes: 3

Related Questions