ConstructorParameters & InstanceType
ConstructorParameters<T> and InstanceType<T> are the class-oriented counterparts to Parameters and ReturnType. Given a constructor type — typically typeof SomeClass — they extract the tuple of arguments new expects and the type of the object it produces. They are invaluable for writing factories, dependency-injection containers, and generic wrappers that must operate over arbitrary classes without hard-coding each one. Like their function cousins, both are tiny conditional types using infer. This page covers usage, implementation, and how they combine.
ConstructorParameters: the new() argument tuple
ConstructorParameters<T> returns a tuple of the types the constructor accepts. Pass the class value through typeof to get its constructor type.
class HttpClient {
constructor(baseUrl: string, timeout: number, retries = 0) {}
}
type Args = ConstructorParameters<typeof HttpClient>;
// [baseUrl: string, timeout: number, retries?: number]
const args: Args = ["https://api.dev", 5000];
const client = new HttpClient(...args); // ✅
The tuple preserves labels and optionality exactly like Parameters. Spreading it into new HttpClient(...args) is fully type-checked, so missing or extra arguments are rejected.
InstanceType: the produced object type
InstanceType<T> yields the type of an instance the constructor creates — equivalent to the class name used as a type, but derived from the constructor value.
class Repository<T> {
items: T[] = [];
add(item: T) {
this.items.push(item);
}
}
type Repo = InstanceType<typeof Repository>;
// Repository<unknown>
function makeRepo<C extends new (...a: any[]) => any>(Ctor: C): InstanceType<C> {
return new Ctor();
}
This matters in generic code where you only have the constructor as a value (C) and need to name the type of what new Ctor() returns — there is no Ctor type to reference directly.
How they are implemented
Both are conditional types constrained to abstract new (...args: any) => any, so they also accept abstract class constructors.
type MyConstructorParameters<T extends abstract new (...a: any) => any> =
T extends abstract new (...args: infer P) => any ? P : never;
type MyInstanceType<T extends abstract new (...a: any) => any> =
T extends abstract new (...args: any) => infer R ? R : any;
infer P captures the constructor’s parameter list as a tuple; infer R captures the instance type. The abstract modifier in the constraint lets these work on classes you cannot instantiate directly.
A type-safe generic factory
Combining both utilities lets you write one factory that constructs any class while keeping argument and result types correct.
function create<C extends new (...args: any[]) => any>(
Ctor: C,
...args: ConstructorParameters<C>
): InstanceType<C> {
return new Ctor(...args);
}
const c = create(HttpClient, "https://api.dev", 5000);
// c: HttpClient ✅
create(HttpClient, "https://api.dev"); // ❌ Error: missing 'timeout'
The ...args: ConstructorParameters<C> ties the factory’s rest arguments to the class’s real constructor, and the InstanceType<C> return type means c is correctly typed as an HttpClient with no casting.
Comparison
| Utility | Input | Output |
|---|---|---|
ConstructorParameters<T> | typeof Class | tuple of new arguments |
InstanceType<T> | typeof Class | type of new Class() |
Parameters<T> | function type | tuple of call arguments |
ReturnType<T> | function type | return type |
Pass
typeof MyClass(the constructor), notMyClass(the instance type). Feeding the instance type fails thenew (...) => anyconstraint and produces an error.
Best Practices
- Always pass
typeof Class; these utilities operate on the constructor, not the instance type. - Use
InstanceType<C>to name a generic class’s instance when you only hold the constructor value. - Combine both in factory helpers so argument lists and return types track the class automatically.
- Remember the constraint allows
abstractconstructors, so abstract classes work as inputs. - Prefer deriving from a single class over maintaining a parallel hand-written constructor signature.
- Reach for
Parameters/ReturnTypefor plain functions and these two for classes. - Spread
ConstructorParameters<C>intonew Ctor(...)to keep instantiation fully checked.