Try   HackMD

My JSDoc-TypeScript cheatsheet

JSDoc-TypeScript
JavaScript with JSDoc that is understood by TypeScript compiler. For what is supported by TypeScript compiler or langauge server, see JSDoc Reference.

JSDoc's annotation looks like: /** your annotation here */.

Type annotations

The list is NOT meant to be exhaustive.

Vol. 1 To annotate types

  • @type {type}: Declare or, when placed before a parenthesis, cast an expression to type (like the TS keyword as).
    • @satisfies {type}: Assert but not casting the type (like the TS keyword satisfies).
    • Support casting to const!
  • @this {type}: Declare the type of this in the next function context.
  • @param {type} name: Declare the type of name as type. Mostly useful for annotating function parameters.
    • Supports optional arguments ([name=value]).
    • Supports arguments in nested object path (name.prop) useful when a param is destructured.
  • @returns {type}: Declare the return type of the function.
  • @extends {type}: Annotate a class to refine the super type of it. Only useful when you need to write complex types like Set<T>.

Vol. 2 To construct types

  • @typedef {base} type: Declare type that extends base.
    • @property {type} name: further annotating its properties. Only effective when base is a plain object.
    • @callback type: assume base is a function type. Use @param and @returns to annotate the function.
  • @template {base} T: Declare a template argument T to be used in conjunction with other declarations in the same block.
    • {base} works as if it appears in type<T extends base>.
    • Supports multiple arguments (T,U,...).
    • Supports default arguments ([T=object]).
  • @import { ... } from 'module': Works like import type in TS.
    A new feature in TypeScript v5.5 (Finally!)

Some neat TypeScript features that cannot be easily expressed:

  • var!: Assert some variable is not null. You need to write out the exact type to cast.
  • Specifying template arguments for method invocations. If the inference is wrong, you have to write out the complete type definition and cast. For instance Object.entries<T>, it looks like
    ​​const x = { [Math.random().toString()]: Math.random() }
    ​​// uh wait a minute; I looked up the type definition:
    ​​// entries<T>(o: { [s: string]: T; } | ArrayLike<T>): [string, T][];
    ​​// doing inferencing in my head, I should write:
    ​​const entries = /** @type {[string, number][]} */ (Object.entries(x))
    
  • Interfaces. @typedef defines types, not interfaces. I suggest one always create a .d.ts file as a supplement file to store your project-wide types/namespaces/interfaces.
  • The imported value having implicit any type. There is no way to slient the error, since there is no way to cast that variable upon importing.
  • WIP

Suppressors

  • // @ts-nocheck: Add at the beginning of a JS file to enable/disable checking the entire file.
  • // @ts-ignore: Ignores any error in the following line.
  • // @ts-expect-error: Same as before, but if there is no error in the next line, an error is raised instead.

jsconfig.json

  • checkJs
  • strict

WIP

.d.ts

.d.ts is notorious to get it right. Especially when you insist on pure JavaScript.

See also