Type checks can verify that permitted usage compiles and invalid usage fails. These tests complement runtime tests because runtime success does not prove an API’s type constraints.
Before you start
You should be comfortable with JavaScript values, functions and objects. Use a TypeScript project with strict checking enabled when trying the examples. Separate what the compiler proves from what must still be checked when values arrive at runtime.
The practical goal is to reason through this situation: An expected-error fixture ensures UserId cannot be passed to an OrderId parameter. Read the walkthrough first, then try the interview exercise before opening its answer. The important part is explaining the decision and its consequences, rather than remembering a definition alone.
Step-by-step walkthrough
Step 1: Specify accepted usage
Write a compile-time fixture showing the intended inferred result. Runtime tests cannot establish that callers receive a useful static type.
Step 2: Specify rejected usage
Place an expected-error directive immediately before the intentionally invalid call. Keep the example narrow so an unrelated error cannot satisfy it unnoticed.
Step 3: Run the supported compiler
Check fixtures with the package’s strict options. When the API changes, investigate both newly accepted bad calls and newly rejected good calls.
Worked scenario
An expected-error fixture ensures UserId cannot be passed to an OrderId parameter.
function get<T, K extends keyof T>(object: T, key: K): T[K] {
return object[key];
}
const count: number = get({ count: 3 }, 'count');
// @ts-expect-error unknown keys must stay rejected
get({ count: 3 }, 'missing');The successful assignment protects numeric inference. The rejected call protects key constraints. If the error disappears, TypeScript reports the unused expected-error directive, making the regression visible.
Common mistake
An unmaintained suppression can hide unrelated failures if its surrounding code changes.
Verify the behavior
Temporarily loosen key to string and confirm the rejection fixture fails. Keep separate runtime checks for actual property-access behavior; type tests do not execute the function.
Interview exercise
Protect a generic helper’s inference.
Answer and reasoning
Include successful inference fixtures and targeted rejected calls; run them under the supported compiler configuration.
Continue learning
Compare the scenario with the TypeScript interview questions and test your understanding with the TypeScript MCQs. For terminology and implementation details, consult the reference material.