【问题标题】:Declare Interfaces in typings file for JavaScript在 JavaScript 的类型文件中声明接口
【发布时间】:2018-12-06 04:44:24
【问题描述】:

项目信息

我正在开发一个使用 .d.ts 文件的 JavaScript 项目。这是我之前提出的问题的后续问题,因此您可以查看有关该项目的更多信息here

问题

虽然我通常可以从类型文件中提取函数,但我无法提取为空或纯粹由接口组成的接口或命名空间。我通过为每个接口创建一个const 实现并在cmets 中使用@typeof ConstantImplementation 暂时解决了这个问题。请参阅下面的示例:

// Typings File
export namespace test {
    export interface ITest {
        foo: string;
        bar: number;
    }
    export const Test: ITest;
}

// JS File
if (undefined) var {Test: ITest} = require("globals.d.ts").test; 
// Above line shows `unused var error`

/* @type {typeof ITest} */
var x = {};
x.foo = "hello";
x.bar = 3;
// if I do `x.` intellisense should suggest `foo` and `bar` 

我想知道是否有更好的方法来解决这个问题,最好是不会引发错误的方法(使用 eslint ignore line 不是解决方法)。

澄清

这个问题不是关于从类型文件中获取功能。这纯粹是为了让 VSCode 智能感知与类型接口一起工作。这是一张图片来解释我想要什么(圆圈内的两条线):

【问题讨论】:

    标签: javascript interface visual-studio-code intellisense .d.ts


    【解决方案1】:

    我发现了一些无需任何额外配置且使用简单的东西,但您需要配置 tsconfig.json。

    tsconfig.json

    {
      "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "moduleResolution": "node",
        "baseUrl": "../",
        "noEmit": true,
        "target": "es5"
      }
    }
    

    test.d.ts

    export = Test
    export as namespace Test
    declare namespace Test {
      interface ITest {
        foo: string;
        bar: number;
      }
    }
    

    test.js

    /**
     * @type {Test.ITest}
     */
    let x;
    

    【讨论】:

      【解决方案2】:

      所以我能够使用 JSDoc 解决问题

      test.d.ts

      export namespace test {
          export interface ITest {
              foo: string;
              bar: number;
          }
      }
      

      test.js

      /**
       * @type {import("./test").test.ITest}
       */
      
      let x;
      
      x.
      

      智能感知现在有效

      我还发现一件事是,如果您添加 jsconfig.json

      jsconfig.json

      {
          "compilerOptions": {
              "checkJs": true
          }
      }
      

      你的智能进一步提高

      Update-1

      正如@nickzoum 所指出的,如果您像下面这样定义test.d.ts

      export interface ITest {
          foo: string;
          bar: number;
      }
      
      export as namespace test;
      

      那么你也可以在 JS 中使用下面的表单进行智能感知

      /** @typedef {import("./test").ITest} ITest */
      
      /** @type {ITest} */
      var x = {};
      x.
      

      【讨论】:

      • 看来您仍然可以将声明包装在您想要的命名空间中。但是您还必须在全局范围内使用export namespace as randomName。因此,如果您只是将export namespace as randomName 添加到您的第一个示例, you can do @typedef {import("./test")} JSDoc` 然后/** @type {JSDoc.test.ITest} */
      【解决方案3】:

      我认为您的问题可能存在概念上的误解。听起来您希望接口在运行时可用。 Typescript 接口纯粹是一个编译时概念。他们不编译任何东西。它们在运行时不存在。

      我把你的这部分代码放到了一个名为interf.d.ts的文件中:

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

      然后我创建了文件test.ts

      import { Interfaces } from "./interf";
      
      const x: Interfaces.Interface = {
          property: "abc",
      };
      
      console.log(x);
      

      我没有收到编译错误,它执行得很好。正如预期的那样,接口 被导出。您稍后导出的const 不需要导出接口(无论如何它导出一个接口,它导出一个const 声明符合接口,但const 不是接口)。

      但是,如果您试图在编译后的 JavaScript 中找到与您的界面相对应的内容,您将找不到它,原因是我在上面给出的:它是一个编译时构造。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-07
        • 1970-01-01
        • 1970-01-01
        • 2017-05-28
        • 2020-03-13
        • 1970-01-01
        相关资源
        最近更新 更多