ThisParameterType<Type>

Extracts the type of a function's explicit this parameter, or unknown when it has none.

Signature
type ThisParameterType<T> = T extends (this: infer U, ...args: never) => any ? U : unknown;
  • Added in TypeScript 3.3

Parameters

ParameterTypeDescription
$Tany typeA function type, normally obtained with `typeof someFunction`. Non-function types simply yield `unknown`.

Return value

U — the declared `this` type, or `unknown`The type declared for the function's `this` parameter. If the function type declares no `this` parameter, the result is `unknown`.

Errors

Nothing — an input with no `this` parameter is not an error, it silently produces `unknown`.

A function can declare a fake first parameter named this to state what receiver it expects: function toHex(this: number) { ... }. The parameter is erased at compile time — it never appears in the emitted JavaScript and never counts as an argument — but it makes fn.call, fn.apply and fn.bind type-safe. ThisParameterType reads that declaration back out.

The place you actually need it is a wrapper around a function you did not write. If you are writing function invokeOn(receiver: ???, fn: F), the only correct type for receiver is ThisParameterType<F>; anything else either over-restricts callers or throws away the checking the this annotation was there to provide. The same applies to decorators, method-borrowing helpers, and adapters that re-bind callbacks onto a different object.

What trips people up

  • The fallback is unknown, not never or void. A function with no this annotation therefore accepts any receiver through this utility, and a missing annotation looks exactly like a correct one until something misbehaves at runtime.
  • Arrow functions cannot declare a this parameter at all — they close over the surrounding this — so they always yield unknown.
  • Under strictBindCallApply the extracted type is enforced on call/apply; without that flag those methods accept anything regardless.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Type the receiver argument of a helper that calls a foreign function with `.call()`.
  • Constrain a method-borrowing utility so only compatible objects can be passed.
  • Document the required context of a callback in an event-handler API.

Frequently asked questions

How do I get the type of this inside a function?

Use `ThisParameterType<typeof fn>`, which reads the function's explicit `this` parameter. The function must declare one — `function fn(this: Ctx, ...)` — otherwise you get `unknown`.

Why does ThisParameterType return unknown for my function?

Because the function has no explicit `this` parameter. Arrow functions and ordinary functions without the annotation both produce `unknown`; add `this: YourContext` as the first parameter, which is erased at compile time and does not affect call sites.

Does the this parameter count as a real argument?

No. It exists only in the type system and is removed from the emitted JavaScript, so `function f(this: Ctx, x: number)` is still called as `f(1)` and `Parameters<typeof f>` is `[number]`.

More examples

Borrowing a method onto a compatible object

`runWith` never mentions `Row`, yet passing an object without a `cells` array is rejected, because the receiver parameter is typed from the function's own `this` declaration. The valid call prints `a | b | c`.

Example · typescript
interface Row { cells: string[] }

function renderRow(this: Row, sep: string): string {
  return this.cells.join(sep);
}

function runWith<F extends (...args: any) => any>(
  ctx: ThisParameterType<F>,
  fn: F,
  ...args: Parameters<F>
): ReturnType<F> {
  return fn.apply(ctx, args);
}

console.log(runWith({ cells: ["a", "b", "c"] }, renderRow, " | "));
// runWith({ nope: true }, renderRow, " | ");
// Error: Object literal may only specify known properties — 'cells' is missing.

unknown means the annotation was forgotten

The two functions look interchangeable but their extracted context types are not: one is `{ n: number }` and the other is `unknown`, which accepts a string. Output is `1 2` then the string — a reminder that the safety comes from the annotation, not from the utility.

Example · typescript
const counter = { n: 0 };

// Annotated: the receiver is checked.
function bump(this: { n: number }) { this.n += 1; return this.n; }
type BumpThis = ThisParameterType<typeof bump>; // { n: number }

// Not annotated: anything goes.
function bumpLoose() { return 1; }
type LooseThis = ThisParameterType<typeof bumpLoose>; // unknown

const ok: BumpThis = counter;
const anything: LooseThis = "a string is fine here";

console.log(bump.call(ok), bump.call(ok));
console.log(anything);

Discussion

  • Be the first to comment on this lesson.