Ts-loader: Unable to import .d.ts files

Created on 22 Sep 2017  路  33Comments  路  Source: TypeStrong/ts-loader

Why can't ts-loader find my .d.ts files? When I build with webpack, I get:

ERROR in ./src/filter.ts
Module not found: Error: Can't resolve './png' in '/Users/bronson/testproj/src'
 @ ./src/filter.ts 1:0-15
 @ ./src/content.ts

But, when I call tsc directly, it loads png.d.ts and compiles the project just fine. tslint works too. The problem appears to only affect ts-loader (and atl).

Here is filter.ts, the error occurs on the first line, import './png':

import './png'
import * as logo from './icon-blue.png'

And here's png.d.ts, not much to it:

declare module '*.png' {
  const value: any
  export = value
}

Interestingly, if I replace the es6 import with a reference, it works. ts-loader builds this without error:

///<reference path="png.d.ts"/>
import * as logo from './icon-blue.png'

And, for reference, an example of calling tsc directly:

tsc --module es6 --target es6 --moduleResolution node --allowSyntheticDefaultImports --noImplicitReturns --strict --outDir /tmp --traceResolution src/filter.ts

======== Resolving module './png' from '/Users/bronson/testproj/src/filter.ts'. ========
Explicitly specified module resolution kind: 'NodeJs'.
Loading module as file / folder, candidate module location '/Users/bronson/testproj/src/png', target file type 'TypeScript'.
File '/Users/bronson/testproj/src/png.ts' does not exist.
File '/Users/bronson/testproj/src/png.tsx' does not exist.
File '/Users/bronson/testproj/src/png.d.ts' exist - use it as a name resolution result.
======== Module name './png' was successfully resolved to '/Users/bronson/testproj/src/png.d.ts'. ========

How can I debug this further? Is there a way to get ts-loader to tell me how it's resolving modules, similar to --moduleResolution? Thanks!

  • __ts-loader version__: 2.3.7
  • __TypeScript version__: 2.5.2
wontfix

Most helpful comment

Finally, I use awesome-typescript-loader to solve this problem...

All 33 comments

Hi @Bronson,

I'm learning ts-loader, webpack and vuejs. I inclined to use standard javascript but thought I include these additional tools to experience.

In my opinion using these addition tools provide addition overhead for little gain. But I still need to know.

Can you tell me if the .d.ts or definition file is required to export my javascript objects? Here's a link to my repo.

Here is my webpack.config.js, pretty standard: https://gist.github.com/bronson/dfabd3e5ed5362d5b5a6223d96f7d944

Removing the resolveLoader doesn't change the problem -- it still can't find .d.ts files.

I'm afraid I don't really have time to dive into this, but it does look a little strange that you're importing png's. ts-loader is only interested in TypeScript and JavaScript. Do you want to use require if this not TypeScript?

I think my understanding of this is incorrect, but I was expecting that ts-loader and webpack would naturally compile to standard javascript. The result bundle.js doesn't export anything that is usable from the javascript debugger console.

I must using window["key"] = classname to get anything meaningful.

export {classname as default, classname} doesn't work for me. Arrg! Trying to determine if pure javascript would be simpler even though typescript javascript keeps developer inline with type language similar to C#, Java and others.

@johnnyreilly ah, I never considered using require. That seems so 2016... Sure, I can try it.

I've banged together a repro repo: https://github.com/bronson/ts-loader-test

I'll add some console.logs and see if I can find some obvious issue.

OK, Webpack can't load png.d.ts because of my extensions: https://github.com/bronson/ts-loader-test/blob/master/webpack.config.js#L7

When I added .d.ts to that list, webpack finds png.d.ts. Good! But now ts-loader complains:

ERROR in ./png.d.ts
Module build failed: Error: Typescript emitted no output for /Users/bronson/tester/png.d.ts.
    at successLoader (/Users/bronson/tester/node_modules/ts-loader/dist/index.js:48:15)
    at Object.loader (/Users/bronson/tester/node_modules/ts-loader/dist/index.js:30:12)
 @ ./content.ts 1:0-15

And now I'm confused... It's true that declaration files don't produce any output. So how are they supposed to work with ts-loader?

This is for a different problem, isn't it? https://github.com/TypeStrong/ts-loader#declarations-dts

@johnnyreilly is this what you mean by using require? (link to file)

require('./png')
import * as logo from './icon-blue.png'

Now I get the error

ERROR in ./content.ts
(1,1): error TS2304: Cannot find name 'require'.

which makes sense... and, again, I'm not sure how it's supposed to work. arg.

Hurrr, I feel like I'm losing my mind. When I delete lines requiring png.d.ts entirely, the compile seems to work.

Are all *.d.ts files automatically loaded? I haven't found anything in the docs describing why, when I delete all references to png.d.ts from my code, the compile works perfectly. (I'm sure it's getting loaded because, when I remove it, I get errors about being unable to load the png modules)

So, I appear to have stumbled on a solution, but I don't know why it works.

Png's are not TypeScript and so the TypeScript compiler doesn't need to know about them. And yes d.ts files are imported as import/requires take place. Why don't you take a look at a boilerplate project since you're struggling?

Sure. There are like a zillion of them, with all sorts of different ways of invoking webpack.

Can you recommend one?

Sorry, caching issue. Your second comment just appeared. Thanks!

@bronson your not losing your mind. I remember context switching between a few different languages and spent more than a day trying to determine why VSCode debugger local variable had correct read and formatted a string. However, the UI display was wrong. I simple forget escaping the backslash '\' character. ...Rest my case

ASP.NET MVC app using jQuery $(document).ready(...) stop working and I think typescript with VueJS for smaller apps is too much but it helps demonstrates my understanding of current open source tools.

Welcome to the open source neighborhood.

...Spread the word Karega K Scott was never in\out TODAY!

I have a .d.ts file that has some extra props added to the window object.

interface Window {
  APP: {
    STATE: string;
    ID: string;
  };
}

Im using VSCode and get no errors in the IDE. But when compiling with ts-loader i get errors:

TS2339: Property 'APP' does not exist on type 'typeof window'.

So it seems like no .d.ts files are loaded when ts-loader is bundling?

@stormpat The Window class is a built-in object. I wasn't aware it could be overridden. However, the document suggest creating individual modules/namespaces. This eliminate vendor naming conflicts. I think TypeScript provides inheritance hierarchy too. Review the documentation.

@johnnyreilly He's not trying to import a .png file here, he's trying to import a file called png.d.ts.

I'm having the same issue trying to import global.d.ts:

import "./global";

results in this output (even though tsc has no issue):

Module not found: Error: Can't resolve './global' in 'C:\...'

However using a triple-slash reference seems to work. Is that the expected way to include .d.ts files?

///<reference path="./global.d.ts"/>

However using a triple-slash reference seems to work. Is that the expected way to include .d.ts files?

No. I suspect you need to explicitly include a reference to your .d.ts file in your tsconfig.json. Try that and report back

TSC and TypeScript have different behaviour when it comes to module resolution. I feel we could handle this better and I'm open to someone implementing something which results in a nicer experience. Whether that makes sense as a "now it just works" or in the form of a helpful error with suggested fix when compiling I'm not sure.

If someone wants to provide a minimal repo that illustrates this issue it would be very helpful. With that a straight fix to ts-loader might be possible for someone to attempt.

Finally, I use awesome-typescript-loader to solve this problem...

@nonoroazoro it's great that you found something that solves your problem. I'd love to see a PR that solves this for ts-loader.

@johnnyreilly 馃槶 Sorry I made a mistake, it seems that the ATL didn't solve the problem...

But after I separated the declaration files into a new types folder (rather than put them in the same dist folder), the warning is gone, and I'm using ts-loader again 馃槃

I've the exact same issue as @bronson

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Closing as stale. Please reopen if you'd like to work on this further.

I am also facing the same issue.

I have a async-child-process module and I am using
import { join, Result } from "async-child-process";

I have created a typings folder and has an async-child-process.d.ts file in it.
tsc -p ./ works fine however when I use webpack with ts-loader, I get the error:
error TS7016: Could not find a declaration file for module 'async-child-process'.

Did anyone find a fix for this ?

meet same issue, need help

Please re-open this issue, it is still happening for me as well. And I have not found a workaround or solution yet.
Or maybe continue from this issue, as it might be related: https://github.com/TypeStrong/ts-loader/issues/1036

If you'd like to work on it that'd be amazing!

I have solved my issue by re-declaring the module I want to add/override typings for, and this is handled correctly by ts-loader during a webpack build.

Note: this method replaces the complete module, so you would have to copy and paste any existing definitions even if you don't change them.

Create a file for example: @types/MyNewTypings.d.ts
with the following content:

declare module "TheExtactModuleNameYouWantToChange" {
    // Optionally import modules if used in your new typings
    import {Foo} from "RequiredModule";

    export class TheExactClassNameYouWantToChange {
        constructor();

        // Define your new properties of TheExactClassNameYouWantToChange 
        public MyNewProperty: Foo;
    }
}

And in your tsconfig.json you should add the folder where your typings (in this example @types) are defined last to the "include" property, like so:

"include": [
    "src",
    "folderThatContainsImportantCode",
    "@types" 
]

I imagine the import type syntax from TypeScript 3.8 should make this a non-issue. Just use import type whenever you import a .d.ts file and it should work without error.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Closing as stale. Please reopen if you'd like to work on this further.

Just adding a final note for the public record.

.d.ts files aren't bundled because TypeScript doesn't output any JS (because they only contain types which don't exist in JS). And (I guess?) empty files have no need to be bundled. Then later when your code tries to import that file it doesn't exist.

To fix, ensure you always use import type whenever you import a .d.ts file. The import type won't exist in the generated code, so a file that doesn't exist won't be imported.

The only weakness is that import/export type don't support * wildcard syntax. But it's not a huge issue.

My problem was my tsconfig.json wasn't include-ing the directory with the d.ts file in it.

Was this page helpful?
0 / 5 - 0 ratings