从typescript中获取内部javascript文件

时间:2016-10-17 22:12:11

标签: javascript typescript

我的项目中有一个js文件,我需要从ts文件中使用它。

js文件路径为“javascript / jsToConsume.js”。

ts文件路径是“typescript / client.ts”

我在路径“typings / internal / jsToConsume.d.ts”中添加了一个声明文件,其内容如下:

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

在我的client.ts中我尝试使用它:

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

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

'../javascript/jsToConsume'标有红线,我收到以下错误:

  

TS2307:找不到模块'../javascript / jsToConsume'

BTW代码运行完美,这只是一个TSC错误。

的javascript / jsToConsume.js:

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

任何帮助都将深表感谢!

2 个答案:

答案 0 :(得分:5)

如果您在--allowJs中将true标记作为tsconfig.json传递,它会告诉TypeScript编译器也编译JavaScript文件。因此,将此标志设置为true,TypeScript将了解您在JavaScript文件中定义的模块,并且您不需要使用声明文件做任何额外的诡计。

因此,示例tsconfig.json文件可能如下所示:

{
  "compilerOptions": {
    "allowJs": true
    "module": "commonjs",
    "noImplicitAny": true,
    "target": "es6"
  },
  "exclude": [
    "node_modules"
  ]
}

https://www.typescriptlang.org/docs/handbook/compiler-options.html

当然,配置文件完全取决于您的项目,但您只需添加"allowJS": true作为"compilerOptions"之一。

注意:从TypeScript 1.8

开始提供

相关发行说明如下:

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

- 编辑 -

在回应有关要求类型以及内部JS导入的评论时,我想出了以下内容。但是,如果在向JavaScript模块添加类型时遇到这么多麻烦,我建议将文件转换为TypeScript并至少输入所有导出(事实上,回头看这个编辑,这看起来真的没必要,除非无论出于何种原因,将JS转换为TS都是绝对不可能的。但无论如何......

您仍会在"allowJs": true中传递tsconfig.json,但您可以为所需的JavaScript模块创建界面,然后在TS文件中键入导入。下面提供了一个示例,JS文件和TS文件更加充实,以显示可能性:

文件夹结构

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_;

因此,在从模块导入单个成员和默认值时,只需为每个成员提供所需的类型。然后,在使用import * as ...时,您可以为模块的公共导出提供接口。

注意 但是你必须有一个很好的理由,为什么你不想只是将你的JS文件更改为TS。想一想您希望文件的类型,并且您可以控制它们,因为它们是项目的内部,因此听起来就像TS存在的确切用例。您无法控制外部模块,因此您可以构建声明文件以创建用于与库交互的接口。如果您决定在JavaScript中添加类型,那么可以通过将其设置为TypeScript来实现。

答案 1 :(得分:3)

对于外部模块,问题在于:

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

代码甚至没有它,因为你有参考:

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

使用外部模块的正常方式只有一行(https://www.typescriptlang.org/docs/handbook/modules.html):

import * as jsToConsume from 'jsToConsume';

更好的是将命名空间重命名为module:

declare module jsToConsume{...}

这是针对外部模块的

但是如果你只有内部模块,最好使用没有命名空间的模块,只需:

export function func1(): void;

然后您可以将其用作:

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

 import * as someName from '../javascript/jsToConsume';
someName.func1();