【问题标题】:How to export a function from a module as a class member如何将模块中的函数导出为类成员
【发布时间】:2021-10-27 06:33:38
【问题描述】:

如何将模块中的函数导出为类属性?

当类有一个属性指向模块内的一个函数时,该属性就像它的 private 一样,不管任何修饰符(在此处添加 public 不会做任何事情)

例如,这里有 3 种方法来定义属性(例如 a、b、c),它们都做同样的事情,但没有一种方法能满足我的需求——即在其他模块中定义函数等类身体不会失控

// myModule.ts
/** typedef this is a test */
export function func(msg) {
  console.log(msg);
}

// myClass.ts
import * as myModule from './myModule';
export class MyClass {
  a(msg) { return myModule.func(msg); }
  b = (msg) => myModule.func(msg);
  c = myModule.func;
}

// index.ts
import { myClass } from './myClass';
const classInstance = new myClass();
classInstance.a('test'); // works but this way i cannot get typedefs from a module
classInstance.b('test'); // added just for completness, but its same problem as c
classInstance.c('test'); // works but tsc complains about property 'c' does not exist on type 'MyClass'

【问题讨论】:

  • c = myModule.func; 应该在这里工作。我将您的代码复制到 this sandbox 中,它似乎完全按照您的预期工作。当我将鼠标悬停在 classInstance.c 上时,我在 IDE 中看到文档注释就好了。我确实必须将myClass 的大写修改为MyClass,但是,因为您发布的代码中不存在myClass。您能否发布一个显示问题的最小可重现示例?
  • 对不起大写的类型,否则就是这样 - 而你的沙箱正是我想要的。但是在我的环境中classInstance.c() 可以工作,但无法为其获取 IntelliType,当我手动键入它时,它会显示关于属性不存在的警告——比如它的私有属性。也许不同的 TSC 配置?顺便说一句,我正在使用 4.4
  • 您可以尝试使您的tsconfig.json 与该沙箱中的相同,看看它是否表现得更好,然后尝试查看可能导致此问题的不同设置。还有一些 IDE 的缓存类型信息,需要偶尔重新启动以完全刷新应用程序类型。或者使用相同的设置启动一个空白且完全空的项目,看看您是否也有问题。
  • @AlexWayne 我在挖掘之后在下面添加了更多详细信息 - 找到了原因,但仍然不知道如何解决它,我还不能使用 esnext。跨度>

标签: javascript typescript


【解决方案1】:

开始挖掘 - 问题不在于在 TypeScript 项目中完全工作时,
问题是在将带有类的 TS 模块编译为 JS,然后从其他任何地方使用该 JS 时

由 TSC 编译,target=es2020
TSC 隐藏属性,并且它们仅在 typedef 可用时才可见
如果 typedef 因任何原因不可用,则属性 .b.c 将报告为 does not exist on type MyClass

基本上,TSC 创建的 JS 可以有效执行,但在其他方面并不正确

myClass.js

export class MyClass {
  constructor() {
      Object.defineProperty(this, "b", {
          enumerable: true,
          configurable: true,
          writable: true,
          value: (msg) => myModule.func(msg)
      });
      Object.defineProperty(this, "c", {
          enumerable: true,
          configurable: true,
          writable: true,
          value: myModule.func
      });
  }
  a(msg) {
      return myModule.func(msg);
  }
}

myclass.d.ts

export declare class MyClass {
    a(msg: string): void;
    b: (msg: string) => void;
    c: typeof myModule.func;
}

当 TSC 用 target=es5 编译时,以太方式是可以的
因为它不依赖Object.defineProperty

myClass.js

var MyClass = (function () {
  function MyClass() {
      this.b = function (msg) { return myModule.func(msg); };
      this.c = myModule.func;
  }
  MyClass.prototype.a = function (msg) {
      return myModule.func(msg);
  };
  return MyClass;
}());

你猜怎么着?使用target=esnext,TSC 生成完美的代码

myClass.js

import * as myModule from "./myModule";
export class MyClass {
    a(msg) {
        return myModule.func(msg);
    }
    b = (msg) => myModule.func(msg);
    c = myModule.func;
}

基本上,ES5 根本没有类,ES2018 有,但使用Object.defineProperty 定义每个属性,这太可怕了。 ESNext 是干净的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    相关资源
    最近更新 更多