转换 class 类型并调用静态 属性

Casting a class type and calling a static property

我在一个使用 jsdoc/typescript 验证的 javascript 项目中工作,但在转换类型时遇到问题,之后使用它的静态 属性。

使用导入类型时出现以下问题:

// @ts-check -- foo.js
export default class Foo {
    static bar() {}
}

// @ts-check -- bar.js

/** @typedef {import('./foo').default} Foo */

const HopefullyFoo = /** @type {unknown} */ ('Foo');

const foo = /** @type {typeof Foo} */ (HopefullyFoo);

foo.bar();

输出:

src/components/bar.js:7:31 - error TS2693: 'Foo' only refers to a type, but is being used as a value here.

7 const foo = /** @type {typeof Foo} */ (HopefullyFoo);
                                ~~~

如果我将所有内容都放在一个文件中似乎没问题:

// @ts-check

class Foo {
    static bar() {}
}

const LikelyFoo = /** @type {unknown} */ ('Foo');

const foo = /** @type {typeof Foo} */ (LikelyFoo);

foo.bar();

// No errors

如果我不转换为 typeof,我会得到这个错误,所以我认为这也不对。

// @ts-check

class Foo {
    static bar() {

    }
}

const LikelyFoo = Foo;

const foo = /** @type {Foo} */ (LikelyFoo);

foo.bar();

输出

src/components/foo.js:13:5 - error TS2576: Property 'bar' is a static member of type 'Foo'

13 foo.bar();
       ~~~

这可能吗?

class 的类型是此 class 的构造函数创建的对象将具有的类型。此类型仅包含实例级字段,这就是您正确使用 typeof 运算符的原因。问题是运算符不能应用于类型,而是需要一个值。 通常导入的情况下

import Foo from "./foo";

你得到了类型和值(构造函数),但在 jsdoc 导入的情况下你只得到了一个类型。 因此,如果由于某种原因您无法导入实际值,您可以在 class 定义旁边为 typeof Foo 添加一个别名:

foo.js

// @ts-check -- foo.js
export default class Foo {
  static bar() {}
}
/** @typedef {typeof Foo} FooCtor */

然后使用它

// @ts-check -- bar.js

/** @typedef {import('./foo').FooCtor} FooCtor */

const HopefullyFoo = /** @type {unknown} */ ('Foo');

const foo = /** @type {FooCtor} */ (HopefullyFoo);

foo.bar();

PS: 说实话,我从来没有见过这样使用 TS,所以我可能是错的。