ThisParameterType<Type>
Extracts the type of a function's explicit this parameter, or unknown when it has none.
type ThisParameterType<T> = T extends (this: infer U, ...args: never) => any ? U : unknown;- Added in TypeScript 3.3
Parameters
| Parameter | Type | Description |
|---|---|---|
$T | any type | A 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, notneverorvoid. A function with nothisannotation 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
thisparameter at all — they close over the surroundingthis— so they always yieldunknown. - Under
strictBindCallApplythe extracted type is enforced oncall/apply; without that flag those methods accept anything regardless.
Example
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`.
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.
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