在JavaScript VSCode项目中添加自定义类型文件

时间:2017-10-11 02:09:18

标签: javascript visual-studio-code typescript-typings .d.ts

问题

我正在使用VSCode开发JavaScript项目。我正在使用UMD设计模式,而vscode intellisense无法识别来自另一个文件的模块的导出。我在名为globals.d.ts的文件中添加了所有声明。很遗憾,我无法从JavaScript文件中加载globals.d.ts声明。

示例模块声明

export namespace ModuleName {
    export interface Item {
        toString(): string;
        property: string;
        name: string;
    }
}

示例JavaScript文件

(function (global, factory) {
    "use strict";
    if (typeof ModuleName === "undefined" && typeof require === "function") global.ModuleName = require("./mymodule.js");
    if (typeof exports !== "undefined" && typeof module !== "undefined") factory(exports);
    else factory(global.OtherModule = global.OtherModule || {});
})(this, (function (exports) {
    "use strict";

    function myMethod() {

    }

    exports.myMethod = myMethod;
    return exports;
}));

我尝试了什么

我尝试使用typings install "globals.d.ts"创建typings文件夹,typings.json等。这仅在打开VSCode中的打字文件然后关闭并重新打开应用程序后才能运行。这只有在我保持typings文件打开时才有效。这不是添加界面声明的非常方便的方法。

关于VSCode(8个月前)

Version: 1.17.0
Shell: 1.7.7
Node: 7.9.0
Architecture: x64

关于VSCode(现在)

Version: 1.24.1
Shell: 1.7.12
Node: 7.9.0
Architecture: x64

行为没有变化。

3 个答案:

答案 0 :(得分:9)

普通的Node.JS解决方案

创建下一个文件(名称应相同):

lib.js 
lib.d.ts

在lib.js内部编写一些代码,让我们说一遍:

function whenDo(params) {
    return params;
}

module.exports = whenDo;

在lib.d.ts内部编写以下代码:

declare function wd(params: wd.Params): wd.Params;

declare namespace wd {
    interface Params {
        name: string;
    }
}

export = wd;

然后,在某个地方创建文件以使用新创建的功能,并放置以下代码:

const wd = require('./lib/lib');

const opt = wd({name:'drag13'});
console.log(opt.name);

魔术来了,一切都很好。 enter image description here

代码从这里https://github.com/Drag13/WhenDo/blob/master/src/index.d.ts被盗

答案 1 :(得分:4)

针对使用babel的用户的ES6导入语法解决方案

创建下一个文件(名称应相同):

lib.js 
lib.d.ts

在lib.js内部编写一些代码,让我们说以下代码:

export const testMethod = (name, params) => params && params.age ? `hello ${name} with age: ${params.age}` : `hello ${name}`;
export const myConst = {
     name: 'test',
     age: 5
 };

在lib.d.ts内部编写以下代码:

declare namespace MyModule {
    interface IParams { age: number; }

    function testMethod(name: string, params: IParams): string;

    const myConst: {
        name: string,
        age: number
    }
}
export = MyModule;

然后,在某处创建文件以使用新创建的功能,并放置以下代码:

import { testMethod } from "./lib/lib";

const name = 'drag13';
const r = testMethod(name, { age: 5 });
console.log(r);

现在,智能感知应该可以很好地处理参数和结果。

enter image description here

但是。这种方法要求您使用babel来与node.js友好并进行导入。如果您尝试将代码从导入样式更改为要求样式,您仍然会看到类型和参数,但是智能化将失败。

简单的通天符检查:

npm i babel-preset-env babel-cli
./node_modules/.bin/babel-node index.js --presets env

我的VsCode版本为1.24.1

答案 2 :(得分:4)

致谢

这个答案大部分是由Vitalii's answer复制/启发的,但是由于必须对其进行一些修改才能与我的项目一起使用,因此我还要添加这个答案。

解决方案

在使用外部代码的每个文件的顶部,我添加了:

if (undefined) var { -List of Namespaces used- } = require("./globals");

未定义是具有恒定假值而不触发eslintjshint的最短,最简单的方法(我想到了)。这样可以确保在“仍然”需要jsdoc的同时,永远不会运行代码。

我使用var代替了letconst,因为它不会停留在if范围内,而是停留在全局文件范围内。

这实际上将在{}中声明变量(如undefined),但是typeof undeclaredtypeof undefined都是"undefined",因此没有区别在代码中。

通过在一个文件中包含所有声明,我可以通过在一行中分解一个require语句来获取所有名称空间。 但是请记住,为使此功能正常运行,您需要在打字文件中使用export而不是declare

解决方案问题

我无法从JavaScript文件查看globals.d.ts中的接口。

export namespace Namespace {
    export interface Interface {
        property: string;
    }
}

我已通过将名称空间的接口重命名为Interfaces(也修复了globals.d.ts中的所有引用)并通过使用实现接口的常量创建了另一个命名空间,来暂时解决了此问题,如下所示:< / p>

export namespace Interfaces {
    export interface Interface {
        property: string;
    }
}

export namespace Namespace {
    export const Interface: Interfaces.Interface;
}

在JavaScript注释中使用globals.d.ts中的命名空间也遇到了麻烦。为了解决此问题,我在类型的前面添加了typeof,例如:/** @param {typeof Namespace.Interface} */