Skip to content
Chapter 5Lesson 8

Quiz - TypeScript bug-class moves

Quiz progress

0 / 0

You’re modeling a request lifecycle that produces exactly four runtime states (idle, loading, success, error). A teammate proposes:

type RequestState = {
status: 'idle' | 'loading' | 'success' | 'error';
data?: User;
error?: Error;
};

Why is this still the flag-set anti-pattern in disguise?

Because data and error are top-level optionals — the type still admits status: 'loading' with data set, and every consumer of state.data has to null-check.

Because the discriminant should be named kind, not status, for non-async lifecycles.

Because the union has no Result variant, so the function can’t return a failure shape.

In the optimistic-mutation machine, why does the optimistic variant carry an original: string field that confirmed does not?

Per-state invariants — rollback is only callable from optimistic, and it needs the pre-change value to restore. confirmed is past the rollback window, so it has nothing to remember.

To work around a TypeScript limitation where union variants must differ by at least two fields to narrow correctly.

Because confirmed derives original from the server response and doesn’t need to store it.

A teammate writes an exhaustive switch on a discriminated union and ends it with event satisfies never instead of return assertNever(event). Which framing is correct?

satisfies never is the right reach when the bottom is structurally unreachable and no runtime throw is needed — the check erases at compile time. assertNever is the default for real handlers where a malformed payload reaching the bottom should fail loudly.

They’re equivalent — satisfies never is just the newer syntax for the same runtime throw, so always prefer it.

satisfies never is unsafe because it doesn’t fire a compile error when a variant is missed; only assertNever enforces exhaustiveness.

Which of these strings deserve a brand under the senior test (crosses a schema boundary, has semantic identity, can be confused with another value of the same shape)? Select all that apply.

A StripeCustomerId value read from a Stripe webhook payload.
A WebhookSecret used to verify incoming Stripe events.
The body of a user-submitted comment.
A search query the user typed into a filter input.

A teammate writes:

const LOCALES = ['en', 'es', 'fr'];
type Locale = (typeof LOCALES)[number];

and is surprised Locale resolves to string instead of 'en' | 'es' | 'fr'. What’s the fix?

Add as const to the value: const LOCALES = ['en', 'es', 'fr'] as const. Without the freeze, the array’s inferred type is string[], and indexing it by number returns string.

Replace [number] with [keyof typeof LOCALES][number] only works on tuples that were declared with explicit length.

The pattern doesn’t work on arrays; hand-write type Locale = 'en' | 'es' | 'fr' instead.

You need: the same Invoice shape with id, createdAt, and updatedAt removed, then every remaining field optional (a PATCH /invoices/:id body). Which expression? Select all that apply.

Partial<Omit<Invoice, 'id' | 'createdAt' | 'updatedAt'>>
Omit<Partial<Invoice>, 'id' | 'createdAt' | 'updatedAt'>
Pick<Invoice, Exclude<keyof Invoice, 'id' | 'createdAt' | 'updatedAt'>>

Which generic signature lets pluck(user, 'id') return the precise type at that key (e.g., a branded UserId) instead of the union of all field types?

<T, K extends keyof T>(obj: T, key: K): T[K]
<T>(obj: T, key: keyof T): T[keyof T]
<T extends Record<string, unknown>>(obj: T, key: string): unknown

Quiz complete

Score by topic