How to import js-modules into TypeScript file?
Asked Answered
C

8

165

I have a Protractor project which contains such a file:

var FriendCard = function (card) {
    var webElement = card;
    var menuButton;
    var serialNumber;

    this.getAsWebElement = function () {
        return webElement;
    };

    this.clickMenuButton = function () {
        menuButton.click();
    };

    this.setSerialNumber = function (numberOfElements) {
        serialNumber = numberOfElements + 1;
        menuButton = element(by.xpath('.//*[@id=\'mCSB_2_container\']/li[' + serialNumber + ']/ng-include/div/div[2]/i'));
    };

    this.deleteFriend = function () {
        element(by.css('[ng-click="deleteFriend(person);"]')).click();
        element(by.css('[ng-click="confirm()"]')).click();
    }
};
module.exports = FriendCard;

Path to the file is ./pages/FriendCard.js.

I have no problems with its import to another file using require():

var FriendCard = require('./../pages/FriendCard');

So, I've decided to import this file to the TypeScript file just like that:

import {FriendCard} from './../pages/FriendCard'

I'm using WebStorm. It tells me that (TS2305) it has no exported member 'FriendCard'.

Maybe I have to configure tsconfig.json file somehow, but I still don't know how it works. Could you help me?

Carib answered 19/12, 2016 at 9:34 Comment(1)
"I'm using WebStorm, so it tells me, that (TS2305) it has no exported member 'FriendCard'." Just a small note -- TS2305 means that the warning/error is produced by actual TypeScript compiler/language service and not actual WebStorm .. as IDE does not use such numbering in their own inspections/parsers.Alberto
H
190

You can import the whole module as follows:

import * as FriendCard from './../pages/FriendCard';

For more details please refer the modules section of Typescript official docs.

Recent Updated Solution : We need to tweak the tsconfig.json to allow JS modules import. credits to @paulmest, @ben-winding @crispen-gari solutions below.

{
  "compilerOptions": {
    "allowJs": true
  }
}
Hinson answered 19/12, 2016 at 10:36 Comment(3)
Thanks for articulating "./" in front of the actual relative path. This makes all the difference in path resolution at the compile time.Frankel
Is this up to date? I still get the same error... Could not find a declaration file for module ...Camelopardus
@nathan-h You probably need to modify the tsconfig file... more info here: https://mcmap.net/q/149247/-how-to-import-js-modules-into-typescript-fileEisler
E
85

I'm currently taking some legacy codebases and introducing minimal TypeScript changes to see if it helps our team. Depending on how strict you want to be with TypeScript, this may or may not be an option for you.

The most helpful way for us to get started was to extend our tsconfig.json file with this property:

// tsconfig.json excerpt:

{
  ...
  "compilerOptions": {
    ...
    "allowJs": true,
    ...
  }
  ...
}

This change lets our JS files that have JSDoc type hints get compiled. Also our IDEs (JetBrains IDEs and VS Code) can provide code-completion and Intellisense.

References:

Eisler answered 5/7, 2019 at 20:59 Comment(2)
I've put inside compilerOptions ``` lang-js { "compilerOptions": { ..., "allowJs": true } ... } ```Dangerous
Same use case like me but imo makes the migration possible harder because you start taking all legacy code as dependency into typescript.Dia
S
17

2021 Solution

If you're still getting this error message:

TS7016: Could not find a declaration file for module './myjsfile'

Then you might need to add the following to tsconfig.json

{
  "compilerOptions": {
    ...
    "allowJs": true,
    "checkJs": false,
    ...
  }
}

This prevents typescript from trying to apply module types to the imported javascript.

September answered 21/1, 2021 at 13:46 Comment(1)
I found this solved my problem if using ts-jest, on a .ts file which imports a .js file which imports a .ts file. A totally unavoidable situation with a clean solution.Blackjack
P
16

In your second statement

import {FriendCard} from './../pages/FriendCard'

you are telling typescript to import the FriendCard class from the file './pages/FriendCard'

Your FriendCard file is exporting a variable and that variable is referencing the anonymous function.

You have two options here. If you want to do this in a typed way you can refactor your module to be typed (option 1) or you can import the anonymous function and add a d.ts file. See https://github.com/Microsoft/TypeScript/issues/3019 for more details. about why you need to add the file.

Option 1

Refactor the Friend card js file to be typed.

export class FriendCard {
webElement: any;
menuButton: any;
serialNumber: any;

constructor(card) {
    this.webElement = card;
    this.menuButton;
    this.serialNumber;
}



getAsWebElement = function () {
    return this.webElement;
};

clickMenuButton = function () {
    this.menuButton.click();
};

setSerialNumber = function (numberOfElements) {
    this.serialNumber = numberOfElements + 1;
    this.menuButton = element(by.xpath('.//*[@id=\'mCSB_2_container\']/li[' + serialNumber + ']/ng-include/div/div[2]/i'));
};

deleteFriend = function () {
    element(by.css('[ng-click="deleteFriend(person);"]')).click();
    element(by.css('[ng-click="confirm()"]')).click();
}
};

Option 2

You can import the anonymous function

 import * as FriendCard from module("./FriendCardJs");

There are a few options for a d.ts file definition. This answer seems to be the most complete: How do you produce a .d.ts "typings" definition file from an existing JavaScript library?

Proctoscope answered 19/12, 2016 at 10:35 Comment(0)
L
9

I tested 3 methods to do that...

Method1:

      const FriendCard:any = require('./../pages/FriendCard')

Method2:

      import * as FriendCard from './../pages/FriendCard';

Method3:

if you can find something like this in tsconfig.json:

      { "compilerOptions": { ..., "allowJs": true }

then you can write: import FriendCard from './../pages/FriendCard';

Luvenialuwana answered 19/9, 2020 at 11:26 Comment(1)
thank you, method 1 solved my problem to import a js libraryGilford
F
1

The answers about adding allowJs: true to your tsconfig.json worked for me, but I also had to make sure the includes: [] block within the tsconfig.json included Javascript files.

{
  "compilerOptions": {
      ...
      "include": ["src/**/*.js"]
      ...
  }
}

Fredrick answered 17/12, 2022 at 4:14 Comment(0)
M
1

apart from adding allowJs and checkJs, like:

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": false
  }
}

make sure that strict option is not set to true.

Marlin answered 21/5, 2023 at 17:45 Comment(0)
J
0

If you want to view references to JS in a TS file, you need to set allowJs to true. If it doesn't work, you may also need to set maxNodeModuleJsDepth, for example, to 3.

Jehiel answered 13/3 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.