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

nic*_*oum 26 javascript visual-studio-code typescript-typings .d.ts

问题

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

示例模块声明

export namespace ModuleName {
    export interface Item {
        toString(): string;
        property: string;
        name: string;
    }
}
Run Code Online (Sandbox Code Playgroud)

示例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;
}));
Run Code Online (Sandbox Code Playgroud)

我尝试了什么

我尝试使用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
Run Code Online (Sandbox Code Playgroud)

关于VSCode(现在)

Version: 1.24.1
Shell: 1.7.12
Node: 7.9.0
Architecture: x64
Run Code Online (Sandbox Code Playgroud)

行为没有变化.

Dra*_*g13 10

Plain Node.JS解决方案

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

lib.js 
lib.d.ts
Run Code Online (Sandbox Code Playgroud)

在lib.js里面写了一些代码,让我们说一下:

function whenDo(params) {
    return params;
}

module.exports = whenDo;
Run Code Online (Sandbox Code Playgroud)

在lib.d.ts里面写这个:

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

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

export = wd;
Run Code Online (Sandbox Code Playgroud)

然后,创建somewhere文件以使用新创建的函数并输入以下代码:

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

const opt = wd({name:'drag13'});
console.log(opt.name);
Run Code Online (Sandbox Code Playgroud)

魔法就在这里,一切都很好. 在此输入图像描述

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


Dra*_*g13 7

使用 babel 的人的 ES6 导入语法解决方案

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

lib.js 
lib.d.ts
Run Code Online (Sandbox Code Playgroud)

在 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
 };
Run Code Online (Sandbox Code Playgroud)

在 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;
Run Code Online (Sandbox Code Playgroud)

然后,创建某个文件以使用新创建的函数并放置以下代码:

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

const name = 'drag13';
const r = testMethod(name, { age: 5 });
console.log(r);
Run Code Online (Sandbox Code Playgroud)

现在,智能感知应该适用于参数和结果。

在此处输入图片说明

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

简单的 babel 检查:

npm i babel-preset-env babel-cli
./node_modules/.bin/babel-node index.js --presets env
Run Code Online (Sandbox Code Playgroud)

我的 VsCode 版本是 1.24.1

  • 如果您使用 babel,则可以在节点应用程序中使用导入。但据我所知这是不可能的,是吗? (2认同)

nic*_*oum 5

致谢

这个答案主要是由Vitalii 的答案复制/启发,但由于它必须稍作修改,以配合我的项目,我也添加了这个答案。

解决方案

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

if (undefined) var { -List of Namespaces used- } = require("./globals");
Run Code Online (Sandbox Code Playgroud)

Undefined 是最短和最简单的方法(我想到的),在不触发eslintjshint. 这确保代码永远不会运行,同时仍然“需要”jsdoc。

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

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

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

解决方案的问题

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

export namespace Namespace {
    export interface Interface {
        property: string;
    }
}
Run Code Online (Sandbox Code Playgroud)

我通过将带有接口的命名空间重命名为Interfaces(还修复了 中的所有引用globals.d.ts)临时解决了这个问题,并使用实现接口的常量创建了另一个命名空间,如下所示:

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

export namespace Namespace {
    export const Interface: Interfaces.Interface;
}
Run Code Online (Sandbox Code Playgroud)

我也无法使用globals.d.tsJavaScript 注释中的命名空间。为了解决这个问题,我typeof在类型前面添加了,如下所示:/** @param {typeof Namespace.Interface} */

更新

我现在找到了一种将接口从.d.ts文件导出到.js文件的方法,你可以在这里找到答案。