Casting a class type and calling a static property

camomileCase :

I'm working in a javascript project using jsdoc/typescript validation and having trouble casting a type, and using a static property of it afterwards.

When using an imported type I have the below problem:

// @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();

Output:

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);
                                ~~~

If I put everything in one file it seems ok:

// @ts-check

class Foo {
    static bar() {}
}

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

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

foo.bar();

// No errors

If I don't cast to typeof I get this error so I don't think that's right either.

// @ts-check

class Foo {
    static bar() {

    }
}

const LikelyFoo = Foo;

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

foo.bar();

Output

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

13 foo.bar();
       ~~~

Is this possible?

Shlang :

Type of a class is a type that an object created by the constructor of this class will have. This type contains only instance level fields, that is why you correctly uses typeof operator. The problem is that the operator cannot be applied to type, instead it needs a value. In case of usual import

import Foo from "./foo";

you get both the type and the value (constructor) but in case of jsdoc import you get a type only. So if you cannot import the real value for some reason you may add an alias for typeof Foo next to the class definition:

foo.js

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

and use it then

// @ts-check -- bar.js

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

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

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

foo.bar();

PS: tbh, I've never seen uses TS this way, so I may be wrong.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=31940&siteId=1