9

As a bit of a fun project, I'm making a "framework" for creating native web components. I've created a webpack loader that parses some XML in custom .comp files and exports an es2015 class. Unfortunately, I can't find a way to import these .comp files in my typescript files.

I've tried importing my custom files in a regular javascript file, and everything works as expected; I can see the loader I created running, and I get the expected output. But when I try to import in a typescript file I just get the error Cannot find module 'test/test.comp'. I tried creating an empty declaration file and noticed the error message changes to File '[path]/test/test.d.ts' is not a module

Here's my webpack config:

mode: 'development',
watch: true,
entry: './test/main.js',
output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'build')
},
module: {
    rules: [
        {
            test: /\.ts/,
            use: 'ts-loader',
            exclude: /node_modules/
        },
        {
            test: /\.comp/,
            use: path.resolve(__dirname, 'core/compose-loader.js'),
            exclude: /node_modules/
        }
    ]
},
resolve: {
    extensions: ['.js', '.ts', '.comp'],
    alias: {
        'core': path.resolve(__dirname, "core/"),
        'test': path.resolve(__dirname, "test/")
    }
}

And my tsconfig.json

{
    "compilerOptions": {
        "outDir": "build",
        "baseUrl": ".",
        "paths": {
            "core": ["core/*"],
            "test": ["test/*"]
        },
        "target": "es2015",
        "typeRoots": ["./core"]

    },
    "include": [
        "test/*.ts"
    ],
    "exclude": [
        "core",
        "node_modules",
        "**/*.comp"
    ]
}
heavygl0w
  • 209
  • 1
  • 3
  • 7

1 Answers1

23

You can define the types for all these files with *.comp in a declarations.d.ts file (or whatever name you choose).

declare module "*.comp" {
  const value: any; // Add better type definitions here if desired.
  export default value;
}

You may need to also add this to typeRoots in your tsconfig.json

{
    "compilerOptions": {
        // Other configuration...
        "typeRoots": [
            "./src/declarations.d.ts"
        ]
    }
}

And now, import value from "./test.comp" should work as expected (at least the types).

Note: for VSCode the definition file should not be higher in the folder structure than the import.

Simon Márton
  • 332
  • 3
  • 10
skovy
  • 5,430
  • 2
  • 20
  • 34
  • Awesome thanks for your reply. It's working now, albeit not quite in the manner I had hoped. At the project root, I have three folders: core, test, and build. I've been trying to run my tests from a `test.ts` file inside the test directory. Your solution worked once I moved my test file outside the test directory into the project root. Is there any way I could get it working from inside the testing folder? – heavygl0w Sep 28 '19 at 22:52
  • I cam here looking for: ``` [tsl] TS2307: Cannot find module './typeDefs/a.gql' or its corresponding type declarations. ``` while working with `apollo-server`, `webpack` and `typescript`. The code was working as `webpack` was loading everything but the `ts-loader` was throwing this annoying error. The `typeRoots` part was not needed and just the `declaration` helped. – Sudhanshu Apr 02 '21 at 04:58
  • I cannot do something like this to define too many declaration file: `"typeRoots": [ "**/*.d.ts" ]` I also tried this one `"types": [ "**/*.d.ts" ]` but they does not work. I have many `.d.ts.` files and some of them are defined globally. – Kasir Barati Feb 01 '22 at 14:44
  • this works but how about if we want to support better initillisense support e.g - file might expose different methods and different files expose different methods. Is there any way to emit dynamic export. – Ujjwal Kumar Gupta Feb 27 '22 at 12:51
  • Is it possible to do `:string as const`? – Kevin Ghadyani Jul 05 '23 at 04:22
  • @KevinGhadyani - are you looking to do `const value: string;` to say the exported value is a `string`? – skovy Jul 05 '23 at 14:24
  • I was hoping the exported value would be the value in the file itself, but don't worry about it. Apparently, I was completely wrong with my approach. You need to convert `.graphql` files to `.ts` to be able to import them properly as a `const` string. – Kevin Ghadyani Jul 06 '23 at 04:47