TypeScript error

TS2775: An assertion function called through an untyped name

  • Error TS2775
  • Tested with TypeScript 5.9

An assertion function (@returns {asserts value is string}) narrows its argument after the call, but only when TypeScript can see the assertion signature without inferring anything: every name in the call, check.assertString(…), must have a declared type. Otherwise the call is TS2775 and nothing is narrowed.

In JavaScript this comes up more often than in TypeScript, because objects, aliases and factory results are usually untyped: an object literal that collects helpers, const assert = assertString, or a function that returns one.

At a glance

CodeTS2775
MessageAssertions require every name in the call target to be declared with an explicit type annotation.
TypeScript's categoryerror
Listed underTypes do not match
Turned on by No option: every checked file reports it
In .js files Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file

The message is TypeScript's own text from its diagnostic messages file (Apache-2.0).

What it looks like

input.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: input.js(14,3): error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. input.js(14,3): error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. input.js(14,3): error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. checked 21 October 2026
/**
 * @param {unknown} value
 * @returns {asserts value is string}
 */
function assertString(value) {
  if (typeof value !== "string") throw new TypeError("Expected a string");
}

const check = { assertString };

/** @param {unknown} input */
export function shout(input) {
  check.assertString(input);error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation.
  return String(input).toUpperCase();
}
An assertion function called through an object with no declared type.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["**/*.js"]
}

What causes it

  • The assertion function is reached through a variable or object whose type is inferred (const check = { assertString }).
  • An alias of the function (const ensure = assertString) without a type.

How to fix it

Call the function by its declared name, or declare the type of what holds it

A function declaration has an explicit signature, so calling assertString(input) directly works. To keep the object, give it a type with @type; the fixed example uses typeof assertString for the property.

input.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
/**
 * @param {unknown} value
 * @returns {asserts value is string}
 */
function assertString(value) {
  if (typeof value !== "string") throw new TypeError("Expected a string");
}

/** @type {{ assertString: typeof assertString }} */
const check = { assertString };

/** @param {unknown} input */
export function shout(input) {
  assertString(input);
  return input.toUpperCase();
}

/** @param {unknown} input */
export function whisper(input) {
  check.assertString(input);
  return input.toLowerCase();
}
Called directly, or through an object whose type is declared.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["**/*.js"]
}

Gotchas

  • A const arrow function with its own JSDoc counts as declared, so /** @param {unknown} v @returns {asserts v is string} */ const assertString = (v) => … can be called directly.
  • After a TS2775 call the argument keeps its old type, so the next line often fails too (TS18046 for an unknown value).

Sources

Last reviewed 21 October 2026.