Provyn Prep · 8 min read

How to pass the Provyn TypeScript advanced assessment

The advanced TypeScript assessment goes beyond everyday type annotations into the type system itself. Questions test whether you understand how the compiler resolves types, not just which keywords to use.

What you will be tested on

  • Conditional types and distributive behaviour
  • Template literal types and string manipulation
  • infer: extraction in conditional and mapped types
  • Variance: covariance, contravariance, and function parameters
  • Mapped types: modifiers, remapping with as, filtering with never
  • Declaration merging and module augmentation

What the assessment tests

The advanced TypeScript assessment is for engineers writing library code, shared type utilities, or complex generic APIs. Questions are built around real-world patterns: building a type-safe event emitter, extracting route params from a URL string type, or creating a DeepReadonly utility.

Conditional types are the highest-weighted area. Every question about conditional types will include a distributive case — what happens when you pass a union type to a conditional type. The answer is that the conditional distributes over the union, processing each member separately and unioning the results.

Conditional types and distributivity

type IsString<T> = T extends string ? true : false. When T is string | number, the result is boolean (true | false), not just true or false — it distributes. To suppress distribution and treat the union as a whole, wrap both sides in a tuple: type IsString<T> = [T] extends [string] ? true : false.

The infer keyword extracts a type from within a conditional. type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never. Know how to use infer in multiple positions in the same conditional type.

Template literal types

Template literal types manipulate string types at compile time. type EventName<T extends string> = `on${Capitalize<T>}` produces "onClick" from "click". The assessment will ask you to write a type that extracts the parameter names from an Express-style route string like '/users/:id/posts/:postId'.

Combining template literals with infer: type ExtractParam<T extends string> = T extends `:${infer Param}` ? Param : never. Chaining this across a union of path segments produces a union of all parameter names.

Mapped types

Mapped types iterate over a union to produce a new object type. type Readonly<T> = { readonly [K in keyof T]: T[K] }. Know how to add (readonly, ?) and remove (-readonly, -?) modifiers.

Remapping with as: type EventHandlers<T> = { [K in keyof T as `on${Capitalize<string & K>}`]: T[K] } transforms each key. Filtering with never: use a conditional type in the as clause to exclude keys — if the condition returns never, the key is dropped from the result.

Three-day prep plan

Day one: open TypeScript Playground and implement ReturnType, Parameters, and Awaited from scratch without looking at the lib.d.ts source. These are the foundational utility types and the assessment builds variations of them.

Day two: implement a DeepReadonly type that recursively makes every property readonly, including nested objects and arrays. This exercise covers every advanced concept: mapped types, conditional types, recursion, and infer.

Day three: read the TypeScript handbook section on variance. The assessment will ask why a function type that accepts a broader parameter type is assignable to one that accepts a narrower type — contravariance of function parameters.

Ready when you are

Take the TypeScript (Advanced) assessment

Sixty minutes. One credential. Free tier — no card required.

Last updated 2026-05-01.