4

I have a project where I introduced Vue for some frontend stuff but I still have a lot of legacy code in TypeScript and jQuery. All the legacy code is in a 'ts' folder and the new Vue single file components and some bootstrapping ts files are in 'src'. It looks all OK in VSCode and even directly calling 'tsc' on the command line works fine but WebPack keeps complaining as soon as I import a declaration/definition (module) from the 'ts' folder.

Project folder structure

+ root
  + php/css/etc
  + ts
    + models
      - LegacyTypeScriptModules.ts
      - PlanDate.ts
    + js-defs
      - tools.d.ts
    - tsconfig.json (to be able to build only legacy code)
  + src
    + components
      - RecentChanged.vue
    + pages
      - Welcome.vue
    - App.vue
    - main.ts
    - tsconfig.json (main configuration)
  - package.json
  - tsconfig.json (only fixing experimentalDecorators issue in VSCode)
  - tslint.json
  - webpack.config.js

Error message npm build

ERROR in ./ts/models/PlanDate.ts Module not found: Error: Can't resolve 'js-defs/tools' in '/Users/username/dev/project-root/ts/models' @ ./ts/models/PlanDate.ts 1:0-45 @ ./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/RecentChanged.vue @ ./src/components/RecentChanged.vue @ ./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/pages/Welcome.vue @ ./src/pages/Welcome.vue @ ./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue @ ./src/App.vue @ ./src/main.ts

Main tsconfig.json in 'src' folder

{
    "compilerOptions": {
        "target": "es5",
        "strict": true,
        "module": "es2015",
        "moduleResolution": "node",
        "lib": [
            "dom",
            "es2015",
            "es2015.iterable"
        ],
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "baseUrl": ".",
        "paths": {
            "*": [
                "*",
                "./*",
                "../ts/*"
            ]
        }
      },
      "include": [
          "**/*",
          "../ts/**/*"
      ]
}

webpack.config.js

module.exports = {
  entry: './src/main.ts',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: "ts-loader",
        exclude: /node_modules|vue\/src/,
        options: {
          appendTsSuffixTo: [/\.vue$/]
        }
      },
...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
    },
    extensions: ['.js', '.vue', '.json', '.ts'],
    modules: [
      'node_modules', 
      path.resolve(__dirname, 'src'),
      path.resolve(__dirname, 'ts')
    ],
...

First Vue file importing a legacy ts module

import Vue from 'vue'
import { ChangedItem } from '../../ts/models/ChangedItem'
import { PlanDate } from "../../ts/models/PlanDate"
import { Customer } from "../../ts/models/Customer"
import { Component, Prop } from 'vue-property-decorator'

@Component
export default class RecentChanged extends Vue {
...

Class/module giving the error

import { IDate, IDateSink, IDateSource} from "./interfaces/IDate";
import { addDays, pad } from "js-defs/tools";

export class PlanDate implements IDate {
...

Module which can't be found

import { IMainOptions } from "models/interfaces/IOptions";

export declare function addDays(d: IDate, n: number, keepTime?: boolean): IDate;
export declare function pad(inputString: any, width: number, paddingCharacter?: string): string;

Notice that the first problem already is that I can't seem to get the absolute paths working in Vue SFC so I already had to compromise to an ugly relative path. (maybe already a first sign of a problem?) This absolute path problem in Vue is consistent over VSCode, tsk and WebPack but I have seperate question on this. I also had problems with some absolute paths in the legacy typescript classes but I can imagine this because it only seems to work from the 'ts' folder and deeper but I don't think this is related as WebPack doesn't seem to complain about the import 'IDate'.

As the bare typescript compiler doesn't have a problem with finding the declaration modules and also VSCode language server isn't complaining I assume it is a problem in the configuration file for WebPack but maybe I'm missing/overlooking something.

I tried both absolute and relative paths to the declaration module but both fail. Also tried other legacy classes that don't depend on other legacy modules and they do seem to work. So it looks like the module resolution fails on the declaration file. In webpack.config.js I already tried things like resolve.alias and resolve.modules but they didn't work or I don't know how to define the path.

Update

After the first comments and answers given below I'm pretty sure it has to do with how my own declaration file is defined, how I should import it or how I configure WebPack to properly find it. Can someone tell me how to use declaration files in Vue+WebPack+TypeScript without getting a 'module not found' or a 'no output emitted' error?

4
  • Are you sure you're able to import definition files as modules? Commented Dec 11, 2017 at 13:30
  • I tried some more classes that only depend on other classes but that does seem to work so it might have to do with the definition file. Either the extension or the contents like the syntax are not accepted. Commented Dec 11, 2017 at 13:40
  • Any luck with this yet? Using a definition file here and have encountered the same error. Commented Jan 11, 2018 at 22:09
  • Unfortunately no, so I converted everything to TS which takes away the need of a definition file. Commented Jan 12, 2018 at 7:42

2 Answers 2

2

When importing .d.ts files make sure you use the type keyword.

import type * as MyTypes from "./types"

Sign up to request clarification or add additional context in comments.

1 Comment

This is the answer! Changing "resolve.extensions" to include '.d.ts' did nothing for me
1

It might be because the file has extension d.ts where your config is set to only look for .ts extensions when importing?

8 Comments

If I add it to the config like this: resolve: { extensions: ['.js', '.vue', '.json', '.ts', '.d.ts'] . I get an other error:ERROR in ./ts/js-defs/tools.d.ts Module build failed: Error: Typescript emitted no output for /Users/username/dev/project-root/ts/js-defs/tools.d.ts. at successLoader (/Users/username/dev/project-root/node_modules/ts-loader/dist/index.js:47:15) at Object.loader (/Users/username/dev/project-root/node_modules/ts-loader/dist/index.js:29:12). Does WebPack need the actual js file that has these functions?
That would be my assumption, definition files are only for typechecking surely?
So how should I handle definition files for my own js code then? This always worked fine for tsc while I was making sure these functions were defined by another js file in the browser.
Well where are the addDays and pad functions actually defined?
Yes. I also made the question more specific to declaration files because other modules seem to be resolved just fine. Any idea on how declaration files should be used in Vue+WebPack+TypeScript?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.