Type expression

Annotate, cast or satisfy

  • Importing and casting
  • Since TypeScript 5.0

There are three ways to connect a value to a type, and they behave differently. @type {Settings} on a declaration annotates it: the variable has type Settings, and the value is checked against it. A cast, /** @type {Settings} */ (value), claims the type: TypeScript checks only that the two types overlap, so missing properties pass. @satisfies {Settings} checks the value like an annotation but leaves the variable with the value's own, narrower type.

The first example puts all three side by side. The cast accepts an object without pageSize, and only the satisfied object still knows that theme is exactly "dark". The @satisfies tag needs TypeScript 5.0.

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
Annotate: the variable has the type /** @type {Settings} */ const a = { … }; const a: Settings = { … };
Cast: claim the type const b = /** @type {Settings} */ ({ … }); const b = { … } as Settings;
Satisfy: check, keep the value's type /** @satisfies {Settings} */ const c = { … }; const c = { … } satisfies Settings;

Examples

settings.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: settings.js(17,7): error TS2322: Type '"light" | "dark"' is not assignable to type '"dark"'. Type '"light"' is not assignable to type '"dark"'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. settings.js(17,7): error TS2322: Type '"light" | "dark"' is not assignable to type '"dark"'. Type '"light"' is not assignable to type '"dark"'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. settings.js(17,7): error TS2322: Type '"dark" | "light"' is not assignable to type '"dark"'. Type '"light"' is not assignable to type '"dark"'. checked 21 October 2026
/** @typedef {{ theme: "light" | "dark", pageSize: number }} Settings */

/** @type {Settings} */
const annotated = { theme: "dark", pageSize: 24 };

// The cast is accepted although pageSize is missing: a cast claims, it does not check.
const cast = /** @type {Settings} */ ({ theme: "dark" });

/** @satisfies {Settings} */
const checked = { theme: "dark", pageSize: 24 };

/** @type {"dark"} */
const fromChecked = checked.theme;

/** @type {"dark"} */
const fromAnnotated = annotated.theme;error TS2322: Type '"light" | "dark"' is not assignable to type '"dark"'.
  Type '"light"' is not assignable to type '"dark"'.

export { cast, fromChecked, fromAnnotated };
Annotate, cast or satisfy: what each does.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
settings.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: settings.js(4,60): error TS8037: Type satisfaction expressions can only be used in TypeScript files. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. settings.js(4,60): error TS8037: Type satisfaction expressions can only be used in TypeScript files. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. settings.js(4,60): error TS8037: Type satisfaction expressions can only be used in TypeScript files. checked 21 October 2026
/** @typedef {{ theme: "light" | "dark", pageSize: number }} Settings */

const settings = { theme: "dark", pageSize: 24 } satisfies Settings;error TS8037: Type satisfaction expressions can only be used in TypeScript files.

export { settings };
The satisfies operator is TypeScript syntax.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Choosing one

Annotate variables that will be reassigned or passed around as the general type, and function parameters. Satisfy fixed values whose details matter later: configuration, lookup tables, route maps. Cast only when you know more than TypeScript can, such as the element behind a selector, and keep the cast next to the code that makes it true.

Gotchas

  • The satisfies operator is TypeScript syntax and TS8037 in a .js file, as the second example shows; use the tag.
  • @satisfies does not widen: if you later need the general type, annotate a second variable with @type.

Questions

When should I use @satisfies instead of @type?

When the value is fixed and you want TypeScript to remember its exact keys and literal values while still checking it against the type.

Sources

Last reviewed 20 October 2026.