Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript cannot find local es6 module; error TS2307: Cannot find module

I am having a hard time getting typescript to recognize the shape of a local es6 module:

convert-time.js

export const minutes = sec => sec * 60
export const hours = sec => minutes(sec) * 60
export const days = sec => hours(sec) * 24
export const weeks = sec => days(sec) * 24
export const years = sec => days(sec) * 365

Note: I would like to figure out how to get this to work without just changing convert-time.js to a typescript file.

Here is the file I am trying to import it into:

index.ts

/// <reference path="../typings/convert-time.d.ts" />

import { minutes, days } from '../test/helpers/convert-time'

Here is the type definition file I created:

convert-time.d.ts:

declare module "convert-time" {
  export function minutes(sec: number): number;
  export function hours(sec: number): number;
  export function days(sec: number): number;
  export function weeks(sec: number): number;
  export function years(sec: number): number;
}

And here is my tsconfig:

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "jsx": "react"
  },
  "files": [
    "typings/index.d.ts",
    "typings/convert-time.d.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Steps tried:

  • Searched StackOverflow for error TS2307: Cannot find module. Most questions are regarding external modules which have type definitions. I couldn't find an example of a local module.
  • Read https://www.typescriptlang.org/docs/handbook/modules.html
  • Read https://www.typescriptlang.org/docs/handbook/module-resolution.html
  • Added typings/convert-time.d.ts to the files section in tsconfig.json.
  • Added /// <reference path='../../typings/convert-time.d.ts' /> to index.ts

None of the above worked! What dark magic must I learn to get this to work? Thanks!

like image 235
Raine Revere Avatar asked Jun 08 '16 18:06

Raine Revere


1 Answers

Regarding ES6

Since you are trying to inter-operate with an ES6 module you will either"

a) Change your tsconfig.json to target ES6 and emit ES6 modules like this:

{
  ...
  "target": "es6",
  "module": "es6",
  ...
}

However I don't think you can use ES6 modules yet in NodeJS.

or:

b) Let TypeScript transpile the ES6 JavaScript module down to ES5 by enabling JavaScript processing in your tsconfig.json under compilerOptions - like the below and making sure that the .js file is included/not excluded:

{
  ...
  "target": "es5",
  "module": "commonjs",
  "allowJs": true,
  ...
}

Regarding your Type Declarations

Have a read at my blog on how TypeScript discovers typings/type declarations and what it expects to see here: https://ivanz.com/2016/06/07/how-does-typescript-discover-type-declarations-definitions-javascript

It appears that this JavaScript file is your own code (not an NPM module), so:

  1. You don't need the /// <reference path="../typings/convert-time.d.ts" /> as long as the file is not excluded or included in tsconfig.json
  2. Ensure convert-time.d.ts is in the same directory as convert-time.js
  3. You don't need to declare a module, so remove the declare module "convert-time" { bit. This is because by having the .d.ts next to the .js it's an "external" module rather than "ambient' (see my blog) (you will need the declare bit if e.g. you were creating typings which are living in your own code for a NPM package)

Basically:

../test/helpers/convert-time.js:

export const minutes = sec => sec * 60
export const hours = sec => minutes(sec) * 60
export const days = sec => hours(sec) * 24
export const weeks = sec => days(sec) * 24
export const years = sec => days(sec) * 365

../test/helpers/convert-time.ts.d:

export function minutes(sec: number): number;
export function hours(sec: number): number;
export function days(sec: number): number;
export function weeks(sec: number): number;
export function years(sec: number): number;

index.ts:

import { minutes, days } from '../test/helpers/convert-time';

tsconfig.json (for ES5 transpiling)

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "allowJs": true,
    "noImplicitAny": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "jsx": "react"
  },
  "files": [
    "/test/helpers/convert-time.ts.d",
    "/test/helpers/convert-time.js",
    "index.ts"
  ]
}
like image 97
Ivan Zlatev Avatar answered Oct 20 '22 08:10

Ivan Zlatev