Advanced Utility Types

TypeScript ships extraction utility types — Parameters , ReturnType , ConstructorParameters , InstanceType , Awaited , and NonNullable — that pull useful types out of existing functions, classes, and promises, all built on the infer keyword you can use yourself.

Learn Advanced Utility Types in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

These utilities are like X-ray glasses for your types. Point them at a function and read off its inputs ( Parameters ) and output ( ReturnType ); point them at a class and see what it's built from ( ConstructorParameters ) and what it becomes ( InstanceType ); point them at a promise and see what's inside ( Awaited ). And infer is grinding your own lens — once you understand it, you can X-ray any structure you like.

1. Extracting From Functions & Classes

Four utilities pull types out of callables and classes: Parameters<F> (args tuple), ReturnType<F> (result), ConstructorParameters<C> (constructor args), and InstanceType<C> (the new result). Combined with typeof , they derive types straight from your code so nothing drifts out of sync.

2. Awaited<T> & NonNullable<T>

Awaited<T> recursively unwraps promise layers to the resolved value type — the type-level version of await . NonNullable<T> strips null and undefined from a type, mirroring the runtime act of filtering out empty values.

3. Build Your Own With infer

Every utility above is built from conditional types plus the infer keyword, which captures part of a type into a variable. is exactly how ReturnType works — and you can write your own (recursive!) utilities the same way.

🎯 Your Turn

Mirror NonNullable<T> across an array by filtering out both null and undefined . Fill in the two blanks marked ___ , then run it.

No blanks this time — just a brief and a starting outline. Build the async loader and read its resolved config, run it, and check your output against the example in the comments.

Practice quiz

ReturnType<F> gives you:

  • A function's arguments as a tuple
  • A class instance type
  • What a function returns
  • The 'this' type

Answer: What a function returns. ReturnType<F> extracts the type a function returns.

Parameters<F> produces:

  • A tuple of the function's argument types
  • The return type
  • A union of arguments
  • The first argument only

Answer: A tuple of the function's argument types. Parameters<F> gives the function's argument list as a tuple type.

To use ReturnType on a function value named createUser you write:

  • ReturnType<createUser>
  • ReturnType(createUser)

These utilities take a type, so pair them with typeof: ReturnType<typeof createUser>.

ConstructorParameters<typeof Point> extracts:

  • The instance type
  • The constructor's arguments as a tuple
  • The class methods
  • The prototype

Answer: The constructor's arguments as a tuple. ConstructorParameters<C> gives the constructor's arguments as a tuple.

InstanceType<typeof Point> is:

  • The type 'new Point()' produces
  • The constructor args
  • A union of methods
  • Always never

Answer: The type 'new Point()' produces. InstanceType<C> is the type of object that calling new on the class produces.

Awaited<Promise<Promise<number>>> resolves to:

  • Promise<number>
  • Promise<Promise<number>>
  • number
  • unknown

Answer: number. Awaited recursively unwraps every Promise layer, flattening to number.

NonNullable<string | null | undefined> is:

  • string | null
  • string
  • null | undefined
  • never

Answer: string. NonNullable<T> strips both null and undefined from the type, leaving string.

Awaited<number> (a non-promise) is:

  • An error
  • Promise<number>
  • never
  • number

Answer: number. Awaited is a no-op on non-promise types by design, so Awaited<number> is just number.

The keyword that captures a type inside a conditional type is:

  • keyof
  • infer
  • typeof
  • extends

Answer: infer. 'infer' introduces a type variable, e.g. T extends (...args: any[]) => infer R ? R : never.

NonNullable only changes the type, so to actually remove null values at runtime you:

  • Need nothing more
  • Must use Awaited
  • Still need a real guard like filter
  • Must use Parameters

Answer: Still need a real guard like filter. Utility types are compile-time only; a runtime guard such as filter(x => x != null) removes the values.