Skip to content

Subtle error when importing typescript definition file into vue file #2132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jan-johansson-mr opened this issue Aug 9, 2018 · 18 comments
Closed

Comments

@jan-johansson-mr
Copy link

Version

3.0.0-rc.12

Node and OS info

Node v10.8.0 / Npm 6.3.0 / Linux WS-001 4.17.13-arch1

Steps to reproduce

  1. vue create test
  2. Add the following to src folder (a simple typescript declaration file, named MyEnums.d.ts):

  export const enum MyEnums {
    C0 = 'ABC',
    C1 = 'DEF'
  }

  1. Add the following to main.ts in src:

  import { MyEnums } from '@/MyEnums';

  interface MyIf {
    enums: MyEnums,
    name: string,
  }

  let p0: MyIf = {
    enums: MyEnums.C0,
    name: 'My name',
  }

  1. Run npm run serve, and you get the error:
  This dependency was not found:

  * @/MyEnums in ./src/main.ts

  1. Rename MyEnums.d.ts to MyEnums.ts
  2. Run npm run serve, and everything is fine.
  3. Rename MyEnums.ts to MyEnums.d.ts
  4. Change the code above to:

  import { MyEnums } from '@/MyEnums.d';

  interface MyIf {
    enums: MyEnums,
    name: string,
  }

  let p0: MyIf = {
    enums: MyEnums.C0,
    name: 'My name',
  }

  1. Run 'npm run serve', and you get the error:
  Using 1 worker with 2048MB memory limit
   94% after seal

   ERROR  Failed to compile with 1 errors                                                                                                                         5:46:44 PM

   error  in ./src/MyEnums.d.ts

  Module build failed (from ./node_modules/ts-loader/index.js):
  Error: Debug Failure. Output generation failed
      at Object.transpileModule (/home/user/temp/ts/test/node_modules/typescript/lib/typescript.js:100526:29)
      at getTranspilationEmit (/home/user/temp/ts/test/node_modules/ts-loader/dist/index.js:231:74)
      at successLoader (/home/user/temp/ts/test/node_modules/ts-loader/dist/index.js:33:11)
      at Object.loader (/home/user/temp/ts/test/node_modules/ts-loader/dist/index.js:21:12)

   @ ./src/main.ts 10:0-38 12:9-16
   @ multi (webpack)-dev-server/client?http://192.168.1.48:8081/sockjs-node (webpack)/hot/dev-server.js ./src/main.ts

  Type checking in progress...
  No type errors found
  Version: typescript 3.0.1
  Time: 1984ms

  1. Even though you get No type errors found, when you browse to the address http://localhost:8081, you get the report: URIError: Failed to decode param '/%3C%=%20BASE_URL%20%%3Efavicon.ico' ..., and a blank web page.

What is expected?

No error when using typescript definition files with solution

What is actually happening?

The build tools are complaining about missing dependency, or when using more specific path (so that I make sure the path ends in .ts) I get 'Output generation failed'.


I run into the issue when building my solution, and after pinning it down to my enums, I realized it has something to do with the naming of the definition files ending in .d.ts and not in .ts.

@trickpeeraze
Copy link

I got the same error when I config typescript with ESLint (airbnb). It seems to work fine when you just use tslint as usual.

@OzairP
Copy link

OzairP commented Sep 18, 2018

Just ran into this issue, super frustrating since it leaves zero trace back to what the issue could be.

EDIT: Ran into this issue because the module I was using did not automatically build.

@NoelDeMartin
Copy link
Contributor

I have run into a similar issue, and I think the problem can be traced back to a known bug from ts-loader: TypeStrong/ts-loader#331

What seems to be causing that error is using the transpileOnly option for ts-loader, and it can be fixed by setting that option back to its default (false). But it is a shame, because the whole point of using that is to make the compilation faster.

A temporal solution is to disable it using the following vue.config.js file:

module.exports = {
    chainWebpack: config => {
        config.module
            .rule('ts')
            .use('ts-loader')
            .loader('ts-loader')
            .tap(options => {
                options.transpileOnly = false;

                return options;
            });
    },
};

@OzairP
Copy link

OzairP commented Oct 18, 2018

After further investigation my issue was caused because one of my node modules did not transpile TS, so the main file did not exist. No error hinted to that, so sounds like the issue might be bigger than that.

@NoelDeMartin
Copy link
Contributor

The approach I indicated above only works for development, to fix it in both production and development use:

module.exports = {
    chainWebpack: config => {
        const rule = config.module.rule('ts');

        rule.uses.delete('thread-loader');
        rule.use('ts-loader')
            .loader('ts-loader')
            .tap(options => {
                options.transpileOnly = false;
                options.happyPackMode = false;

                return options;
            });
    },
};

@OzairP What do you mean that one of your modules doesn't transpile TS, isn't webpack doing the transpilation? In any case, a new app created with the CLI will suffer this problem, so this fixes it for the time being.

@OzairP
Copy link

OzairP commented Oct 20, 2018

I had imported a module via git not npm and npm had not run the build phase so there was no transpiled code.

My point is our cause of the issue is vastly different, there is no debuggable error messages either.

@mmmeff
Copy link

mmmeff commented Nov 9, 2018

I just started seeing this error today. I'm calling tsc 3.1 directly though - no webpack. It started occurring after I upgraded my project from Typescript 2.7 to 3.1.

@OzairP
Copy link

OzairP commented Nov 9, 2018

@mmmeff unfortunetly this is not debuggable. There are numerous reasons it can be happening. I would check your import transformation settings because TS did introduce "esModuleInterop" in tsconfig.

@zaverden
Copy link

I have run into the same problem. Let me add what I found:

Problem appears only if you have some enums in your .d.ts file. It happens because enum is not only a type information that can be stripped, but it has some run-time information (I mean enum values).

I run several tests for simple TS code with babel@7 transpilation without webpack. And I think I found a reason of the issue.

  1. babel transpile enums.d.ts into enums.d.js
  2. in TS code, if you use enum only for typing (like import { SomeEnum } from './enums'; const value: SomeEnum = 2;) then transpiled JS does not have a reference to enum, because babel just strip it. And this case causes no errors
  3. however if you use enum values then transpiled JS has import
// TS
import { SomeEnum  } from './enums'; 
const value = SomeEnum.Qwe;

// Transpiled JS
var _models = require("./enums");
const value = _models.SomeEnum.q;

Now it is obvious that JS expects enums.js file, but we have only enums.d.js. And here it fails.

Well, the core issue is not vue-cli, but I'm not sure where we should report it

@KubaJastrz
Copy link

KubaJastrz commented Jun 21, 2019

You can't export any actual JavaScript code from declaration files (*.d.ts), because TypeScript removes them from the generated output. Here is a playground demo that illustrates what enums are compiled into.

More info here: https://lukasbehal.com/2017-05-22-enums-in-declaration-files/

@ericdfields
Copy link

I'm encountering this with a codemirror embed in my app. Is there are proper solution at this point?

@ux-engineer
Copy link

Encountering this issue when adding an enum to my TypeScript definition files in a Vue CLI project.

@zaverden
Copy link

@ericdfields I've ended up with using string unions instead of enums.

type Direction = 'up' | 'down' | 'left' | 'right'
///
function move(d: Direction) { /* some code */ }
///
move('up')
move('left')
move('dawn')

For me, code looks cleaner. And TS still gets your back with Argument of type '"dawn"' is not assignable to parameter of type 'Direction' check. Auto-completion works too. Looks like a great solution.

@jan-johansson-mr
Copy link
Author

Great points! Declaring enum as @KubaJastrz show produces code, while the Direction type (@zaverden) becomes a type that typescript handles. Illustrates what can be an issue, I guess.

@garyo
Copy link

garyo commented Jan 7, 2021

I've seen this a few times. I think the right solution (given recent enough typescript, I'm using 4.1.3) is import type {Prop} from 'vue/types/options' rather than import {Prop} from 'vue/types/options', i.e. use import type when you're only importing types. YMMV but it seems to help for me.

@nobelhuang
Copy link

As @garyo mentioned, the more elegant way nowadays is using typescript import type statement. But if you are like me who don't want to touch so many import statements in the code base, the other trick I do is using webpack externals config to externalize those definition imports:

{
  externals: [
    (ctx, callback) => {
      /** in order to exclude remaining type imports from final bundles */
      if (/(\.types)$/.test(ctx.request)) {
        return callback(null, '({})', 'root');
      }
      callback();
    },
  ]
}

@jd-solanki
Copy link

Facing same with Vue 2.6.12 😢

@K-walker
Copy link

K-walker commented Sep 15, 2022

这个错误我今天也遇到了,不过我不是定义枚举类型,而是直接报 shims-tsx.d.ts 和 shims-vue.d.ts 文件无法编译

 error  in ./src/shims-tsx.d.ts

Syntax Error: Error: Debug Failure. Output generation failed


ERROR in ./src/shims-tsx.d.ts
Module build failed (from ./node_modules/ts-loader/index.js):
Error: Debug Failure. Output generation failed
    at Object.transpileModule (D:\wink\mg-web-frame\node_modules\typescript\lib\typescript.js:141728:29)
    at getTranspilationEmit (D:\wink\mg-web-frame\node_modules\ts-loader\dist\index.js:397:74)
    at successLoader (D:\wink\mg-web-frame\node_modules\ts-loader\dist\index.js:37:11)
    at Object.loader (D:\wink\mg-web-frame\node_modules\ts-loader\dist\index.js:22:5) @ ./src/ sync ^\.\/.*$ ./shims-tsx.d.ts ./shims-tsx.d
 @ ./src/utils/handleRoutes.js 14:37-68
 @ ./src/store/modules/routes.js 1:0-70 35:23-36 36:25-40
 @ ./src/store/modules/ sync nonrecursive \.js$ ./routes.js
 @ ./src/store/index.js 5:14-58
 @ ./src/main.ts 4:0-28 11:2-7

shims-tsx.d.ts :

import Vue, { VNode } from 'vue'

declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      [elem: string]: any
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests