最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Consume internal javascript file from typescript - Stack Overflow

programmeradmin4浏览0评论

I have a js file in my project which I need to consume from a ts file.

The js file path is "javascript/jsToConsume.js".

The ts file path is "typescript/client.ts"

I've added a declarations file in the path "typings/internal/jsToConsume.d.ts", which its content is as follows:

declare namespace jsToConsume{
    export function func1(): void;
}

In my client.ts I try to consume it:

///<reference path="../typings/internal/jsToConsume.d.ts" />

import * as jsToConsume from '../javascript/jsToConsume'

But '../javascript/jsToConsume' is marked in a red line and I get the following error:

TS2307: Cannot find module '../javascript/jsToConsume'

BTW the code runs flawlessly, it's just a TSC error.

javascript/jsToConsume.js:

function func1(){
    return "Hello World";
}
exports.func1 = func1;

Any help will be profoundly appreciated!

I have a js file in my project which I need to consume from a ts file.

The js file path is "javascript/jsToConsume.js".

The ts file path is "typescript/client.ts"

I've added a declarations file in the path "typings/internal/jsToConsume.d.ts", which its content is as follows:

declare namespace jsToConsume{
    export function func1(): void;
}

In my client.ts I try to consume it:

///<reference path="../typings/internal/jsToConsume.d.ts" />

import * as jsToConsume from '../javascript/jsToConsume'

But '../javascript/jsToConsume' is marked in a red line and I get the following error:

TS2307: Cannot find module '../javascript/jsToConsume'

BTW the code runs flawlessly, it's just a TSC error.

javascript/jsToConsume.js:

function func1(){
    return "Hello World";
}
exports.func1 = func1;

Any help will be profoundly appreciated!

Share Improve this question edited Oct 20, 2016 at 9:13 Alon asked Oct 17, 2016 at 22:12 AlonAlon 12k28 gold badges103 silver badges172 bronze badges 10
  • are you using SystemJS to load the files? If you do you should configure it to correctly map the import to the actual js file. :) – toskv Commented Oct 17, 2016 at 22:19
  • @toskv I don't. it's a server side project in Node.js. – Alon Commented Oct 17, 2016 at 22:23
  • you'd still need to get the correct file loaded via require. :D maybe look into that? – toskv Commented Oct 17, 2016 at 22:25
  • @toskv my JavaScript version is ES6 and I transpile my TypeScript to ES6 so I don't use 'require'. This syntax works fine for me when I consume third party libraries that are installed in node_modules. – Alon Commented Oct 17, 2016 at 22:33
  • @Alon, node_modules is in your NODE_PATH (or some other equivalent variable) variable while the file you are trying to import is not. In this case you'll either need to modify NODE_PATH or provide a path to where your js file is – Dustin Hodges Commented Oct 17, 2016 at 22:36
 |  Show 5 more ments

2 Answers 2

Reset to default 6 +100

If you pass the --allowJs flag as true in your tsconfig.json, it tells the TypeScript piler to pile JavaScript files as well. Therefore, with this flag set to true, TypeScript will know about the modules you've defined in your JavaScript files, and you will not need to do any extra trickery with declaration files.

Therefore an example tsconfig.json file could look like this:

{
  "pilerOptions": {
    "allowJs": true
    "module": "monjs",
    "noImplicitAny": true,
    "target": "es6"
  },
  "exclude": [
    "node_modules"
  ]
}

(https://www.typescriptlang/docs/handbook/piler-options.html)

Of course, the config file would entirely depend on your project, but you would just add "allowJS": true as one of your "pilerOptions".

Note: This is available as of TypeScript 1.8

The relevant release notes are here:

https://www.typescriptlang/docs/release-notes/typescript-1.8.html#including-js-files-with---allowjs

-- EDIT --

In response to ments about requiring types along with your internal JS imports, I have e up with the following. However, if going to this much trouble to add types to your JavaScript modules, I would just suggest converting the file to TypeScript and typing all of your exports at the bare minimum (in fact, looking back at this edit, this seems really unnecessary unless it is absolutely impossible for whatever reason to convert your JS to TS). But anyway...

You would still pass "allowJs": true in your tsconfig.json, but you can create interfaces for the JavaScript modules you want, then type the imports in your TS file. The following provides an example, with the JS file and the TS file a little more fleshed out to show the possibilities:

Folder Structure

src
| - javascript
| | - jsToConsume.js
| - typescript
| | - client.ts
typings
| - typings.d.ts
tsconfig.json

jsToConsume.js

export const yourHair = (adjective) => {
    return `Your hair is ${adjective}`;
}

export let jam = 'sweet';

export class AnotherClass {
    constructor() {
        this.foo = 'bar';
    }
}

export default class Hungry {
    constructor() {
        this.hungry = true;
    }

    speak() {
        return 'More cake please';
    }
}

typings.d.ts

declare interface jsToConsumeModule {
    yourHair: (adjective: string) => string;
    jam: string;
    AnotherClass: AnotherClassConstructor;
}
declare interface Hungry {
    hungry: boolean;
    speak: () => string;
}
declare interface HungryConstructor {
    new (): Hungry;
}
declare interface AnotherClass {
    foo: string;
}
declare interface AnotherClassConstructor {
    new (): AnotherClass;
}

client.ts

import { yourHair as _yourHair_ } from './../javascript/jsToConsume';
const yourHair: (adjective: string) => string = _yourHair_;

import * as _jsToConsume_ from './../javascript/jsToConsume';
const jsToConsume: jsToConsumeModule = _jsToConsume_;

import _Hungry_ from './../javascript/jsToConsume';
const Hungry: HungryConstructor = _Hungry_;

So, when importing individual members and defaults from a module, just give each the desired type. Then you can give an interface for the public exports of the module when using import * as ....

NOTE But you must have a really good reason why you don't want to just change your JS files into TS. Think for a moment that you want types for your files, and you have control of them as they are internal to your project, so that sounds like the exact use case for why TS exists. You can't control external modules, so that's why you build declaration files to create an interface for interacting with the library. If you are determined to add types to your JavaScript, then you can do that by making it TypeScript.

For external modules the problem is in line:

import * as jsToConsume from '../javascript/jsToConsume'

The code will even without it, because you have reference:

///<reference path="../typings/internal/jsToConsume.d.ts" />

Normal way to use external module is only have one line (https://www.typescriptlang/docs/handbook/modules.html):

import * as jsToConsume from 'jsToConsume';

And even better is to rename namespace to module:

declare module jsToConsume{...}

This was for external modules


But if you have only internal modules, it is better to use modules without namespace, just:

export function func1(): void;

Then you can use it as:

import {func1} from '../javascript/jsToConsume';

or

 import * as someName from '../javascript/jsToConsume';
someName.func1();
发布评论

评论列表(0)

  1. 暂无评论