如何正确注释缓存的混合

问题描述

export function Mixin(base) {
  return class extends base {
    foo = "bar";
  }
}

class A extends Mixin(SuperClass) {

}

let a = new A;
a. // suggests foo

这很好用,但就我而言,SuperClass通常是同一构造函数,因此我认为实现缓存是个好主意。

let cache = new Map();
export function Mixin(base) {
  if (!cache.has(base)) {
    cache.set(base,class extends base {
      foo = "bar";
    })
  }
  return cache.get(base);
}

class A extends Mixin(SuperClass) {

}

let a = new A;
a. // no longer suggests foo

因此,为了恢复自动完成功能,我将操作分为两个功能

let cache = new Map();

function Mixin(base) {
  return class extends base {
    foo = "bar";
  }
}

/** 
 * @returns {ReturnType<Mixin>} 
 */
export function Cached(base) {
  if (!cache.has(base)) {
    cache.set(base,Mixin(base));
  }

  return cache.get(base);
}

class A extends Cached(HTMLElement) {}

let a = new A();

a. // suggests foo
a.inn // does not suggest innerHTML

如何注释Cached的返回值,使其知道它将扩展base

我正在考虑以下内容,只是无法弄清楚什么是正确的语法:

/** 
 * @param {T} base
 * @returns {ReturnType<Mixin> extends T} 
 */
export function Cached(base) {

解决方法

cache具有隐式类型Map<any,any>,它不会推断任何其他类型,因为JavaScript对于IDE来说太宽容了,无法检测到{{ 1}}来解析其余代码(即使您使用的是ES6模块,而Map也不会导出)。

如果您不想仅出于键入目的而更改实现,则最好的选择是使用TypeScriptJSDoc type assertions

这是一个最小的示例:

cache
,

所以这让我再次尝试了一次,成功地在我身边自动完成了。 但是,我不得不将cache包装到如下范围中:

class Foo {
    foo = 'bar';
    fooooooo = 'baaaaaaar';
}

class ClassMaker {
    static _cache = new Map();

    /**
     *
     * @param base
     * @return {Foo}
     */
    static getFromBase(base) {
        if (!ClassMaker._cache.has(base)) {
            ClassMaker._cache[base] = class extends base {
            };
            ClassMaker._cache[base].__proto__ = Foo.__proto__;
        }

        return ClassMaker._cache[base];
    }
}

class Baz {
    baz = 'bar';
}

class Unrelated {
    foooooNotCompletedForReference = 'asd';
}

let a = ClassMaker.getFromBase(Baz);

事物会自动完成。还要注意,它不仅仅显示每个符号飞来飞去,即Unrelated类不会填充到自动完成帮助器中。

Screenshot Autocomplete

但是,请注意,没有键入JavaScript,并且如果您希望使用此类功能,则最好使用TypeScript或Dart。 JavaScript中所有这些自动建议只能通过使用附加工具来分析书面代码来尽力而为。它们将是有缺陷的,而且还是无法保证。