简体   繁体   English

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

[英]Add custom typings file in a JavaScript VSCode project

Problem问题

I am working on JavaScript project using VSCode.我正在使用 VSCode 开发 JavaScript 项目。 I am using the UMD design pattern and vscode intellisense cannot recognize the exports of a module from another file.我正在使用UMD设计模式,而 vscode 智能感知无法识别来自另一个文件的模块的导出。 I added all the declarations in a file called globals.d.ts .我在名为globals.d.ts的文件中添加了所有声明。 Unfortunately I couldn't find a way to load the globals.d.ts declarations from my JavaScript files.不幸的是,我找不到从 JavaScript 文件加载globals.d.ts声明的方法。

Example Module declaration示例模块声明

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

Example JavaScript File示例 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;
}));

What I tried我试过的

I tried using typings install "globals.d.ts" which created the typings folder, typings.json etc. This was only working after opening the typings file in VSCode then closing and reopening the app.我试图用typings install "globals.d.ts"这创造了typings的文件夹, typings.json等,这在VSCode打开分型文件,然后关闭并重新打开应用程序后,唯一的工作。 That only worked while I kept the typings file open.这仅在我保持typings文件打开时有效。 This is not a very convenient way to add my interface declarations.这不是添加我的接口声明的非常方便的方法。

About VSCode (8 months ago)关于 VSCode(8 个月前)

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

About VSCode (Now)关于 VSCode(现在)

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

There is no change in behavior.行为没有变化。

Plain Node.JS solution普通 Node.JS 解决方案

Create next files (names should be the same):创建下一个文件(名称应该相同):

lib.js 
lib.d.ts

Inside lib.js write some code, lets say this one:在 lib.js 里面写一些代码,让我们说这个:

function whenDo(params) {
    return params;
}

module.exports = whenDo;

Inside lib.d.ts write this:在 lib.d.ts 中这样写:

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

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

export = wd;

Then, create somewhere file to consume newly created function and put this code:然后,创建某个文件以使用新创建的函数并放置以下代码:

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

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

And magic is here, all worked just fine.魔法就在这里,一切都很好。 在此处输入图片说明

Code was stolen from here: https://github.com/Drag13/WhenDo/blob/master/dts/index.d.ts代码从这里被盗: https : //github.com/Drag13/WhenDo/blob/master/dts/index.d.ts

The approach described here这里描述的方法

ES6 import syntax solution for those who are using babel使用 babel 的人的 ES6 导入语法解决方案

Create next files (names should be the same):创建下一个文件(名称应该相同):

lib.js 
lib.d.ts

Inside lib.js write some code, lets say this one:在 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
 };

Inside lib.d.ts write this:在 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;

Then, create somewhere file to consume newly created function and put this code:然后,创建某个文件以使用新创建的函数并放置以下代码:

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

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

Now, intellisense should works fine for params and result.现在,智能感知应该适用于参数和结果。

在此处输入图片说明

But .但是 This approach requires you to use babel to friend node.js and imports.这种方法需要你使用 babel 来与 node.js 和导入做朋友。 If you will try to change code from import style to require style you still will see types and arguments, but intelisence will fail.如果您尝试将代码从 import 样式更改为 require 样式,您仍然会看到类型和参数,但智能将失败。

Simple babel check:简单的 babel 检查:

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

My VsCode version is 1.24.1我的 VsCode 版本是 1.24.1

Acknowledgment致谢

This answer was mostly copied/inspired by Vitalii's answer , but since it had to be modified a bit, to work with my project, I am also adding this answer.这个答案主要是由Vitalii 的答案复制/启发,但由于它必须稍作修改,以配合我的项目,我也添加了这个答案。

Solution解决方案

On top of each file where I use external code, I added:在我使用外部代码的每个文件的顶部,我添加了:

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

Undefined is the shortest and simplest way (that I thought of) of having a constant false value without triggering eslint or jshint . Undefined 是在不触发eslintjshint情况下拥有恒定假值的最短和最简单的方法(我想到的)。 This ensures that the code will never be run, while still "requiring" the jsdoc.这确保代码永远不会运行,同时仍然“需要”jsdoc。

I used var instead of let or const since it will not stay in the if scope, but rather the global file scope.我使用var而不是letconst因为它不会留在 if 范围内,而是留在全局文件范围内。

This will actually declare the variables inside the {} (as undefined ), but typeof undeclared and typeof undefined are both "undefined" , thus there is no difference in the code.这实际上将声明{}内的变量(如undefined ),但typeof undeclaredtypeof undefined都是"undefined" ,因此代码中没有区别。

By having all the declarations in one file, I can get all the namespaces by destructuring one require statement in one line.通过在一个文件中包含所有声明,我可以通过在一行中解构一个 require 语句来获取所有命名空间。 But keep in mind, that in order for this to work, you need to be using export and not declare in your typings file.但请记住,为了使其工作,您需要使用export而不是在您的打字文件中declare

Problems with Solution解决方案的问题

I cannot view the interfaces in globals.d.ts from JavaScript files.我无法从 JavaScript 文件查看globals.d.ts的接口。

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

I have temporarily fixed this problem by renaming the namespace with the interfaces to Interfaces (also fixed all the references in globals.d.ts ) and created another Namespace with constants that implement the interfaces, like so:我通过将带有接口的命名空间重命名为Interfaces (还修复了globals.d.ts所有引用)临时解决了这个问题,并使用实现接口的常量创建了另一个命名空间,如下所示:

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

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

I also had trouble using the namespaces from globals.d.ts in JavaScript comments.我在 JavaScript 注释中使用globals.d.ts中的命名空间时也遇到了问题。 To solve this problem I added typeof infront of the type, like so: /** @param {typeof Namespace.Interface} */为了解决这个问题,我在类型前面添加了typeof ,如下所示: /** @param {typeof Namespace.Interface} */

Update更新

I have now found a way to export interfaces from .d.ts files to .js files, you can find the answer here .我现在找到了一种将接口从.d.ts文件导出到.js文件的方法,你可以在这里找到答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM