8

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:

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

2
  • 1
    In your compilerOptions you need to have allowJs: true to allow for JavaScript files otherwise it will thow an error. Commented Jul 12, 2017 at 2:25
  • I had this problem. The allowJs: true solved the issue for me Commented Aug 15, 2020 at 16:29

1 Answer 1

6

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"
  ]
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you, Ivan, for the thorough explanation! This did help me understand better how typescript searches for type definitions. I got rid of all of the ambient definitions and references. The build step completes successfully now, but unfortunately at runtime I get "Unexpected token export". Any ideas?
@Raine Where is the error coming from and what is the code?
The code is exactly as you specified. The error occurs in convert-time.js when the server starts, at run-time. It looks like an extra transpilation step is needed somewhere to convert these into commonjs modules?
Note: at the start of step B, commondjs should instead be written as commonjs.
@JamieBirch Good spot! Fixed the typo.
|

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.