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?
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.