| Some of the limitations listed are wrong: > The main limitation is that you don't have access to some TypeScript-specific syntax. > * as, also known as type assertions (or casts) You generally shouldn’t (as the article notes), but you can: const foo = /** @type {Bar} */ ({
something: {
satisfying: 'Bar',
},
});
Note: the parentheses are necessary, they are the JS/JSDoc mechanism for type casts.This also works for `as const`, which is often better when you can use readonly types: const foo = /** @type {const} */ ({
something: 'else',
});
// { readonly something: 'else' }
Better still, the satisfies operator also works (its JSDoc support lagged a bit though): /** @satisfies {Bar} */
const foo = …;
This will infer the type of `foo` and check it for assignability to `Bar`.> * is, also known as type predicates This definitely works: /**
* @param {unknown} value
* @return {value is Foo}
*/
const isFoo = (value) => …
You can also define the guard as a standalone/assignable type: /**
* @callback IsFoo
* @param {unknown} value
* @return {value is Foo}
*/
The @callback tag is ~equivalent to a type alias for a function signature.Also useful, if needed, the @template tag which is roughly equivalent to TS type parameters (generics) which you can use, for example, to assign generic type guards: /**
* @template T
* @callback IsT
* @param {unknown} value
* @return {value is T}
*/
/** @type {IsT<Foo>} */
const isFoo = (value) => …
[Disclaimer: typed this comment on my phone from memory, apologies for any typos or mistakes!] |