Print · All decks
Back to study264 cards · 33 sheets · 66 pages.
Print double-sided, flipping on the long edge, at 100% scale with no margins added by the browser. Answer columns are already mirrored, so each answer lands on the back of its own question. Cut along the dashed lines.
Preview
What is the latest React version, and is 'React 20' real?
What are Actions in React 19?
What does useActionState do?
What does useFormStatus do?
What does useOptimistic do?
What is the use() API?
What are React Server Components (RSC)?
'use client' vs 'use server' — what does each mark?
Async functions passed to a transition or form. React automatically manages the pending state, error handling, optimistic updates, and form resets you used to hand-write.
React 19.2 (19.0 shipped Dec 2024; 19.2 landed Oct 2025). No React 20 exists. React is now stewarded by the independent React Foundation under the Linux Foundation.
Lets a child component read the status (pending, data) of its nearest parent <form> — like context for forms. Classic use: a submit button that disables itself.
Wraps an action and returns [state, formAction, isPending] — replacing hand-rolled loading/error/result state for submissions. Pass formAction straight to <form action={...}>.
Reads a promise or context during render, suspending until the promise resolves. Unlike hooks, use() can be called conditionally and inside loops.
Shows a temporary 'optimistic' value while an async action is in flight, then automatically reverts to the real state when the action completes or fails.
'use client': the boundary where components ship to the browser. 'use server': marks Server Functions callable from the client — NOT server components (those are the default, no directive).
Components that run only on the server and send serialized UI — not JavaScript — to the client. Zero bundle cost. 'use client' marks where the client-side world begins.
What replaced forwardRef?
How does React 19 handle <title> and <meta> tags?
What is the React Compiler?
What is the <Activity> component (19.2)?
What does useEffectEvent do (19.2)?
Name three smaller React 19 quality-of-life changes.
Which headline features are still NOT stable in 19.2?
Interview one-liner: what's the architectural theme of React 19?
Render them anywhere in a component and React hoists them to <head> automatically — native document metadata support, plus stylesheet and async script precedence handling.
Nothing is needed anymore: in React 19, ref is a regular prop on function components. forwardRef is deprecated and codemods remove it.
Wraps UI with modes 'visible' and 'hidden'. Hidden trees keep their state but unmount effects and render at low priority — ideal for tabs or pre-rendering likely-next screens.
A build-time compiler (stable 1.0, late 2025) that auto-memoizes components and values by understanding the Rules of React — retiring most manual useMemo, useCallback, and React.memo.
Context used directly as a provider (<MyContext> instead of .Provider), ref callbacks can return cleanup functions, and hydration errors now show a single readable diff.
Extracts the 'event' part of an effect so it always reads the latest props/state without being a dependency — eliminating stale closures and effects that re-fire too often.
Work moves off the client and out of your hands: RSC shifts rendering to the server, Actions absorb form boilerplate, and the Compiler absorbs memoization — less JS shipped, less code to maintain.
View Transitions and Fragment Refs — real and demoed, but only in Canary/Experimental channels. Saying they're stable in an interview is a red flag.
What do the three letters in CAP stand for?
CAP theorem in one sentence?
Define consistency (in CAP terms).
Define availability (in CAP terms).
Define partition tolerance.
Why is 'CA' not a real choice for distributed systems?
Name some CP systems.
Name some AP systems.
During a network partition, a distributed system must choose between consistency and availability — it can't have both.
Consistency, Availability, Partition tolerance. A distributed system can only guarantee two of the three at once.
Every request to a non-failing node gets a non-error response — though the data may be stale.
Every read receives the most recent write or an error. All nodes appear to hold one up-to-date value (linearizability).
Network partitions are unavoidable in any real network, so P is mandatory. The actual trade-off is only C vs A during a partition.
The system keeps operating even when network failures split nodes into groups that can't communicate.
Cassandra, DynamoDB (default reads), CouchDB, DNS. They stay responsive and reconcile conflicts later (eventual consistency).
ZooKeeper, etcd, HBase, MongoDB (default config), Google Spanner. They refuse or delay requests rather than serve stale data.
What is PACELC?
When should you choose CP in a system design interview?
When should you choose AP?
How does CAP consistency differ from ACID consistency?
What does ACID stand for?
Define atomicity.
Define consistency (in ACID terms).
Define isolation.
When stale or conflicting data causes real harm: ticket booking, inventory, payments, auction bids, distributed locks, leader election.
If Partition: choose Availability or Consistency. Else (normal operation): choose Latency or Consistency. It covers the trade-off even when the network is healthy.
CAP consistency = linearizable reads across nodes. ACID consistency = database invariants and constraints hold after a transaction. Different concepts sharing a letter.
When stale reads are harmless: feeds, like counts, view counters, profiles, analytics. Most systems default to availability.
All or nothing: a transaction either fully completes or fully rolls back. No partial effects are ever visible. It's about failure handling, not concurrency.
Atomicity, Consistency, Isolation, Durability — the four guarantees a database makes about transactions.
Concurrent transactions don't interfere with each other. The result is as if they had run one at a time (serially).
Every transaction moves the database from one valid state to another — constraints and invariants (foreign keys, uniqueness, business rules) always hold.
Define durability.
Name the four standard isolation levels, weakest to strongest.
What is a dirty read?
Non-repeatable read vs phantom read?
How do databases implement atomicity and durability?
What is MVCC?
What is BASE and how does it contrast with ACID?
Which ACID property is the 'odd one out' and why?
Read uncommitted, read committed, repeatable read, serializable. Postgres defaults to read committed; MySQL InnoDB to repeatable read.
Once committed, data survives crashes and power loss — via write-ahead logging, fsync to disk, and (in distributed databases) replication.
Non-repeatable: a row you already read changes between two reads. Phantom: new rows matching your query appear between two reads.
Reading another transaction's uncommitted changes, which may later roll back. Prevented by read committed and above.
Multi-version concurrency control: writers create new row versions instead of overwriting; each transaction reads a consistent snapshot. Readers never block writers.
The write-ahead log (WAL): changes are appended to a sequential log and fsynced before commit. Crash recovery replays the log — redo committed, undo uncommitted.
Consistency. A, I, and D are pure database mechanisms; C is a joint responsibility — the application defines what 'valid' means, the database only enforces declared constraints.
Basically Available, Soft state, Eventually consistent — the availability-first model of AP systems, trading strict guarantees for uptime and scale.
What does SOLID stand for, and where does it come from?
State the Single Responsibility Principle. What counts as a 'reason to change'?
What does an SRP violation look like in a React codebase?
State the Open-Closed Principle.
How would you apply OCP to a switch statement over payment providers that grows every quarter?
State the Liskov Substitution Principle.
Give a classic LSP violation and explain what breaks.
How does TypeScript's type system relate to LSP?
A module should have one, and only one, reason to change. Martin later sharpened 'reason' to mean actor - each module should answer to a single stakeholder or business function, not to a single verb.
Single responsibility, Open-closed, Liskov substitution, Interface segregation, Dependency inversion. Robert C. Martin gathered the five principles around 2000; Michael Feathers rearranged them into the acronym.
Entities should be open for extension but closed for modification: you add behaviour by adding code, not by editing code that already works and is already tested. Polymorphism and composition are the usual mechanisms.
One component that fetches, transforms, formats and renders, so both an API change and a design change land in the same file. Pull data access into a hook and formatting into pure functions, leaving the component to render.
A subtype must be usable anywhere its supertype is expected without breaking the program's correctness. Subtypes may weaken preconditions and strengthen postconditions, never the other way round.
Replace the switch with a registry - Record<Provider, Handler> or a strategy interface - so a new provider is a new entry rather than an edit to the dispatcher. The trade-off: you lose the exhaustive never check that forces you to handle each new case.
TypeScript is structurally typed, so substitutability is judged on shape rather than declared inheritance. Method-shorthand parameters stay bivariant even under strictFunctionTypes - declare them as function properties to get sound, contravariant checks.
Square extending Rectangle: setting width silently mutates height, so any caller written against Rectangle's contract is wrong. The same smell is a subclass that throws NotSupported on an inherited method.
State the Interface Segregation Principle.
What does ISP look like in a TypeScript React app?
State the Dependency Inversion Principle.
Distinguish DIP, dependency injection, and an IoC container.
How do you apply DIP in React or Next.js without a DI container?
What are the main criticisms of SOLID?
How do SOLID, cohesion and coupling relate?
How should a senior engineer talk about SOLID in an interview?
Props typed to exactly what the component reads - Pick<User, 'id' | 'avatarUrl'> rather than the whole User - and one narrow service interface per consumer. Components then compose with partial data and are trivial to test.
No client should be forced to depend on methods it does not use. Prefer several small, role-specific interfaces to one fat one, so a change made for one consumer cannot break or rebuild the others.
DIP is the design principle (depend on abstractions); DI is the technique of passing dependencies in rather than constructing them; an IoC container is tooling that wires DI for you. You can have DI without DIP, and DIP without a container.
High-level policy should not depend on low-level detail; both depend on abstractions, and abstractions do not depend on details. In practice the consumer owns the interface, not the implementation.
The wording is vague, the principles assume 1990s class-based OO, and they are easy to over-apply into indirection nobody asked for. Dan North's CUPID is one alternative, arguing for properties like composable and predictable over rules.
Pass collaborators in as props, context or arguments - a component takes getUser(): Promise<User> instead of importing fetch or the SDK directly. Tests then hand it a fake, with no module mocking or network interception.
Name the axis of change you are protecting and the price you are paying, because abstraction is not free and premature indirection is its own defect. Apply DIP at a volatile boundary such as a telecom or payments provider, and skip it for a stable one.
SRP and ISP push toward high cohesion; OCP, LSP and DIP push toward loose coupling. Cohesion and coupling are the underlying qualities - SOLID is a set of heuristics for moving them in the right direction.
Authentication vs authorization?
Server session vs JWT — what is the real trade-off?
How do you revoke a JWT before it expires?
What cookie flags does a session cookie need?
What does SameSite actually defend against?
Why store tokens in cookies rather than localStorage?
What is refresh token rotation?
Walk the OAuth 2 authorization code flow.
Sessions are revocable but need a lookup; JWTs are stateless but stay valid until they expire. id: 84b9cad0-4dc3-4e3d-8720-47bb2f9b006a
Authentication proves who you are; authorization decides what that identity is allowed to do. id: 81fe3a4a-700b-4358-8c01-574deac5cd8a
HttpOnly, Secure, SameSite, a scoped Path and Domain, and an explicit expiry rather than session-only. id: d63bacda-6876-4f72-a21a-a267efef7020
You cannot, directly — keep access tokens short-lived and check a denylist or version claim on refresh. id: 70975e7e-771e-4dca-832e-6dd26745849c
localStorage is readable by any script, so one XSS leaks the token; HttpOnly cookies are not script-readable. id: db876b62-49ee-46b4-b0d0-2fee41349783
Cross-site requests carrying the cookie automatically — Lax blocks most CSRF, Strict breaks inbound links. id: c56bb26f-f307-44c3-8b76-63720198395e
Redirect to the provider, user consents, provider returns a code, server exchanges it for tokens over the back channel. id: b42b98cd-77e7-4d86-917b-ebee857205b2
Each refresh issues a new token and invalidates the old; reuse of a retired token signals theft and kills the family. id: e476009d-8d58-4c24-b0e8-cd78c080ab98
What is PKCE and who needs it?
What is the state parameter for?
OAuth 2 vs OIDC?
What is an ID token, and how does it differ from an access token?
How do you validate a JWT properly?
Why pin the expected algorithm when verifying?
Walk a one-time-code email login flow.
How do you keep an OTP flow from being abused?
A random value echoed back on redirect, proving the callback belongs to a flow this browser actually started. id: 1eb5273b-dabb-4d1a-8b74-fb2910376ae8
A code verifier and challenge binding the exchange to the client — required for public clients like SPAs and mobile. id: 901102c7-6cc3-4c32-8317-ec49a390385b
The ID token describes the user and is for your app; the access token is a credential for calling an API. id: 35f585ef-25e7-4484-9e7a-58bd640531bb
OAuth 2 grants access to resources; OIDC layers identity on top, adding an ID token and a userinfo endpoint. id: 12a76ade-cd0b-4af1-908a-fd58603dcd55
Otherwise a token can claim alg none or swap RS256 for HS256 and trick the verifier into accepting it. id: 24916417-b1ed-443a-9545-0416e081db29
Verify the signature against the provider's JWKS, then check issuer, audience, expiry and algorithm explicitly. id: 01c44f57-d8f7-4f4c-9e92-c279419bd2e5
Hash and single-use the code, cap attempts, rate limit per address and IP, and expire in minutes not hours. id: 5752f871-a440-46c8-a807-a7b54d8b2dce
Generate a short code, store its hash with an expiry, email it, verify on submit, then issue a session. id: 5926919e-39ab-4d34-bd15-e363f02b0bb1
Why do magic links need care in email clients?
What is session fixation and how do you prevent it?
How should passwords be stored?
What does the auth boundary look like in Next.js?
Why is proxy or middleware alone insufficient for authz?
What is the confused deputy problem here?
How do you handle multi-tenant authorization?
Interview one-liner: what is your default auth stance?
An attacker plants a known session ID; rotate the session identifier on every privilege change or login. id: c7d14f8a-1ce6-46b0-8c44-bd5796115cdc
Scanners and previews follow links, consuming a single-use token before the user ever clicks it. id: 50428de2-23e6-4073-a07d-21f3cead9d9b
Read the session in a Server Component or Server Action; proxy.ts is a coarse gate, not the real authorization check. id: de76d140-eec7-406d-b31e-13dc34f28104
Hashed with a slow, salted algorithm like Argon2 or bcrypt — never encrypted, never a fast general-purpose hash. id: 1501b192-6967-4480-a602-18bbd07924e6
A server component fetching on the user's behalf must scope the query to that user, not just to a valid session. id: 5a0e0378-6e69-4b7b-8ed0-53bd152ec5ee
It guards navigation, not data access — every action and route handler must re-check permissions server-side. id: edd7a79b-9d0d-4a55-baae-ab405c8c1c1b
Short-lived tokens in HttpOnly cookies, rotation on refresh, and authorization enforced at the data boundary.
Scope every query by tenant at the data layer, and treat the tenant as part of the identity, not a request parameter. id: 66ec5682-a08a-4063-bcf0-d6f69839e125
What does idempotent mean for an API?
Which HTTP methods are idempotent by definition?
What is an idempotency key?
How does a server implement idempotency keys?
Why store a hash of the request body alongside the key?
How long should idempotency records be kept?
What happens when two identical requests race?
Why is exponential backoff with jitter the standard retry policy?
GET, PUT and DELETE. POST is not, which is why create endpoints need explicit idempotency keys. id: 94db9390-aecb-4970-b05d-acc074459348
Repeating the same request produces the same result and no extra side effects beyond the first successful call. id: 143cacbe-7300-479b-be28-72d3f55f3501
Store key, request fingerprint and response; on a repeat, return the stored response instead of re-executing. id: e8c0fb7b-f87b-4f4f-a7b1-9db7eb935b6e
A client-generated unique value sent with a request so the server can recognise and replay a retried call. id: def2748e-452c-4e9d-8c26-986186ba1147
Long enough to cover realistic retries — commonly 24 hours — then expired to bound storage growth. id: f9876d5c-ae49-49e4-94a3-f5143ae782bc
To reject a key reused with different parameters, which signals a client bug rather than a genuine retry. id: 9d1295d2-e071-4616-a919-edbe28217b31
Backoff stops retries amplifying an outage; jitter stops every client retrying in the same synchronised wave. id: 5a9cd35f-8143-4691-9ad7-b4841bd3f2cc
The second must block or fail fast; a unique constraint on the key is what actually enforces exactly-one execution. id: b865ea6d-4e98-4f4d-be41-6d591ad86a3a
Which failures should you not retry?
What is the thundering herd problem in retries?
What does a circuit breaker do?
Why do webhooks use at-least-once delivery?
How should a webhook consumer handle duplicates?
How are webhooks authenticated?
Why must you verify the signature on the raw body?
How do you prevent webhook replay attacks?
A downstream recovers and every waiting client retries at once, knocking it straight back over. id: 5cf72589-2777-4bc5-921a-6e9a1033f52a
4xx client errors other than 429 — the request is wrong, so retrying just burns quota and hides the bug. id: daff6172-9fed-4c41-a7c5-0c04fd0f29c3
The sender cannot know whether a lost response means the receiver processed the event, so it retries and may duplicate. id: f4d741c9-8179-40b3-8339-0a4f12d82561
After repeated failures it stops calling a dependency for a cooldown, then lets a trial request test recovery. id: 1bd72dd9-b44b-403f-ab4e-c82818743b25
An HMAC signature over the raw body with a shared secret, verified before parsing and in constant time. id: f476c29d-16f6-4dae-8e33-e59dfaeaad04
Treat the event ID as an idempotency key and record processed IDs, so replays are recognised and dropped. id: 397f95d2-7394-4345-9955-2fa1330b5506
Include a timestamp in the signed payload, reject anything outside a short window, and dedupe on event ID. id: c0c42862-c9aa-47f5-b03b-735a0ae43c70
Parsing and re-serialising changes bytes, so the computed HMAC no longer matches the sender's. id: c2cd13b2-bc7d-4a7d-a0ce-0c7259c1ab21
Why should a webhook handler return 200 immediately?
Can webhook events arrive out of order?
What is the dual-write problem?
What is the transactional outbox pattern?
What is a dead letter queue for?
What is a poison message?
Why is exactly-once delivery a myth in practice?
Interview one-liner: how do you make a payment or provisioning flow safe under retries?
Yes. Carry a version or sequence number per resource and ignore an event older than the state you already hold. id: 9a699e97-94e3-45df-afad-1a939ea041bd
Acknowledge, enqueue, then process asynchronously — slow handlers cause sender timeouts and needless retries. id: a56aa4f6-1839-4be8-9978-96c0612991de
Write the event to an outbox table in the same transaction, then a relay publishes it after commit. id: 2cd904d4-318d-4de1-87d1-136e0e1ab1c9
Committing to your database and publishing an event are separate operations; a crash between them loses one. id: fda784b2-2b0e-4243-bfee-5ded27c42995
One that fails deterministically every time — retrying it forever blocks the queue, so it belongs in the DLQ. id: 43d49e2b-7bc5-4b9f-89f4-0e9023e2d82a
Parking messages that failed every retry, so the pipeline keeps moving and failures can be inspected later. id: 5a15d923-95c3-403b-9779-0c4f4fcceecc
Idempotency key at the edge, outbox for events, dedupe by event ID at the consumer, DLQ for what still fails.
You get at-least-once delivery plus idempotent processing, which yields exactly-once effects. id: 485b2414-c07f-4702-8f2a-f1213e5cec61
What is Kafka, in one line?
Define broker, partition and topic.
Topic vs partition - the actual difference?
What are the fields of a Kafka message?
What does the message key do, and what if you omit it?
What is an offset?
What is a consumer group and what does it guarantee?
Kafka as a message queue vs as a stream?
A broker is a server in the cluster. A partition is an ordered, immutable, append-only log on a broker. A topic is a logical grouping of partitions. id: 8271ae2f-f90f-435e-a468-2fc34531cb64
A distributed event streaming platform - a durable, partitioned, append-only commit log usable as either a message queue or a stream. id: ef4fcf93-ad99-41d0-96eb-07d5f7343518
Value (payload), key, timestamp and headers - all technically optional. Headers are key-value metadata, like HTTP headers. id: a4a48271-4068-4b53-ba64-e6dfd7d6b633
A topic is a logical grouping; a partition is the physical one. Partitions are the unit of parallelism and the only place ordering is guaranteed. id: afe12183-dcaf-40d6-800c-74654f19c720
A sequential ID marking a message's position within a partition. Consumers commit offsets so they can resume where they left off after a restart. id: 8a2d7768-62e9-429f-9ba3-2d76ff4e9fe2
It is hashed to pick the partition, so equal keys stay together and stay ordered. With no key, modern clients use a sticky partitioner and you lose related-message ordering. id: a86b124b-728c-4edf-b163-1cc642c93b78
Same mechanics, different consumption pattern: a queue has one consumer per message; a stream retains the log for replay and multiple independent groups. id: 7fa0f7f4-9e5d-45dd-b961-a3a02d99ffc3
Consumers sharing a topic's partitions - each partition goes to exactly one consumer in the group. Separate groups read the same topic independently. id: 61dcc3d1-2774-4860-86ff-b8e0367f1445
What two steps happen when a producer publishes?
Why is an append-only log the right structure?
How does Kafka replicate a partition?
What is the ISR, and what does acks=all buy you?
Watch-outs when using Kafka from a Node/Next.js app?
Do consumers push or pull? Why?
What ordering guarantee does Kafka actually give?
Default delivery semantics, and how do you get exactly-once?
Immutability simplifies replication and recovery, appending avoids disk seeks, and the simplicity makes scaling by adding partitions straightforward. id: f23f1aaa-a870-4d52-b50b-cf4a809bc7ee
Partition determination (hash the key, or default partitioner), then broker assignment - the client uses cluster metadata to reach that partition's leader. id: 40a7e1f8-7363-4df3-837d-6b2591ca6669
In-sync replicas are the followers fully caught up. acks=all acknowledges only once every ISR has the message - strongest durability, at the cost of latency. id: bc17a2c4-9c7a-4bd0-af19-a0318f321fe4
Leader-follower: one replica takes writes, followers on other brokers sync passively. The controller promotes an in-sync follower when a leader dies. id: 84f9936f-ec3d-4568-b570-1094042de155
Pull - consumers poll at their own rate. Slow consumers self-limit, failure handling is simpler, and batching becomes efficient. id: 25751c6d-d9c6-4617-8089-56c82fb883b8
Clients hold long-lived connections and group membership, which fits badly with serverless handlers. Run producers and consumers in a persistent process or behind a REST proxy. id: eaa802a0-ecf2-48c3-878f-536ef669f2d0
At-least-once by default. Exactly-once needs idempotent producers plus the transactional API - usually better to assume duplicates and make consumers idempotent. id: 1d36be4b-d5d6-4716-9f4d-9fd635bae586
Ordering within a partition only, by offset - not by timestamp, not across a topic. Global ordering means one partition, which means no parallelism. id: d1d67056-53a0-446c-b8c4-d7cae26371bb
What happens when a consumer crashes?
When should you commit the offset?
How do producer retries work, and what is the gotcha?
What does Kafka give you for consumer-side retries?
Rough single-broker capacity for back-of-envelope maths?
Two ways to scale Kafka.
How is a partition chosen from a key?
Four ways to fix a hot partition.
Only after the work is durably done, or you silently drop messages. The more a consumer does per message, the more is redone on failure - so keep consumers small. id: 25a97ecf-42e8-4aa8-ba63-c8a7312b33f2
It resumes from its last committed offset on restart, and the group rebalances so remaining consumers pick up the orphaned partitions. Nothing is missed; some work is redone. id: 7434e18b-9e0a-44c9-a68f-a707c11fcd85
Nothing built in, unlike SQS. The pattern is a retry topic consumed separately, then a dead letter queue after N failures - a fair reason to pick SQS for simple worker queues. id: 6e26d304-6252-4cb5-b713-e5e8f6e1ea39
Producers retry transient failures automatically. Enable idempotent mode alongside retries, or a retried send that actually succeeded becomes a duplicate. id: 974896ab-58b4-4b7e-868f-3a94f0640776
Add brokers, and partition properly. Brokers alone do nothing if topics are under-partitioned - scale the topic, not just the cluster. id: 4305bd52-29cc-4a84-8e67-d74b43e45950
Very hand-wavy, but ~1TB storage and up to ~1M messages/sec on good hardware, with messages under ~1MB. Below that, scaling is not the conversation. id: 4c7af18c-4472-466b-aad2-92d49311db66
Drop the key and spread load (losing ordering); salt the key with a random suffix; use a compound key such as ad ID + region; or apply back pressure and slow the producer. id: f79a2b13-9898-48bb-aef9-9f5bcb2398d3
partition = hash(key) % num_partitions, murmur2 by default. Changing the partition count therefore reshuffles which partition a key maps to. id: b05959f5-ad81-46ec-b997-c665ee61b229
Why are large payloads an anti-pattern, and what instead?
How does retention work, and what is log compaction?
What is KRaft?
What is tiered storage (KIP-405)?
Two producer-side performance levers?
When do you reach for Kafka as a queue in an interview?
When do you reach for it as a stream?
"Always available, sometimes consistent" - so what?
Messages expire by retention.ms (7 days default) or retention.bytes. Compaction instead keeps the latest value per key forever, making the topic a replayable snapshot. id: 33a07f7c-24c1-4f16-b95f-a99ed03fad62
Kafka is not a blob store - big messages hurt memory and network throughput. Write the object to S3 and put a pointer in the message: the claim-check pattern. id: acac941e-5132-4c0d-a306-4a1484d3376a
Brokers keep recent segments on local disk and offload older ones to object storage, so retention is no longer bounded by broker disk. GA in Kafka 3.9. id: db5ee616-49de-45f0-af4d-07993250f9f4
Kafka's own Raft-based metadata quorum, replacing ZooKeeper. Production-ready since 3.3 and ZooKeeper was removed entirely in Kafka 4.0. id: ea87c892-b2df-4b07-a241-6afd1ffa6504
Asynchronous work such as transcoding after upload, work that must stay ordered such as a waiting queue, or when producer and consumer must scale independently. id: b532cdc5-dd3d-4fe5-869d-4b4360ea00c4
Batching (group records per send to amortise network overhead) and compression (GZIP, Snappy, LZ4). Both trade a little latency for a lot of throughput. id: 67758d0f-5870-4df6-b488-0094605ddd6a
Replication and leader failover make cluster-wide outage an unrealistic premise; redirect the question. The interesting failure is a consumer dying.
Continuous real-time processing, such as aggregating ad clicks as they arrive, or fan-out where many independent consumers need the same messages. id: 161ffec7-8ec2-4585-8199-5d9bb3b70f79
When did the App Router become stable, and what is the current Next.js version?
What is the default component type in the App Router?
What does 'use client' actually mark?
Name the special files that define a route segment.
layout.tsx vs template.tsx?
What are route groups and private folders?
How do you write dynamic, catch-all and optional catch-all segments?
What does generateStaticParams do?
Server Components. They run only on the server, can be async, and ship no JavaScript to the browser. id: 7c8b40b4-95c1-4677-8963-bed88a552f34
Stable in 13.4 (May 2023). The current line is 16.3, released August 2026; there is no Next.js 17. id: 32ca8c2c-7c0d-4335-bb8a-aec348f17396
layout, page, loading, error, not-found, template, route, and default (for parallel route slots). id: e1beb9a1-ba1a-40b4-ac42-62cee4415382
The boundary where the client bundle begins. Every module imported below it becomes client code too. id: 29070b96-b8f1-4766-9c37-50803e7df536
(marketing) groups routes without adding a URL segment; _lib opts a folder out of routing entirely. id: 5091e51d-4fae-4aed-a483-24d7aab50906
Layouts persist across navigation and keep state; templates remount and reset state on every navigation. id: 71b81f07-cc59-4cf9-b191-cf4304a05257
Lists the dynamic params to prerender at build time — the App Router replacement for getStaticPaths. id: 055c1eaf-5abc-4147-9915-c8b3eeae5d1c
[id], [...slug] and [[...slug]] — the last also matches the parent path with no segments at all. id: 61daaf88-4538-402f-a676-63245add0129
What changed about params, searchParams, cookies() and headers()?
How does streaming work in the App Router?
Route Handler vs Server Action — when do you use each?
What replaced middleware.ts in Next 16?
What are Cache Components and 'use cache'?
How did caching defaults shift across 14 → 15 → 16?
How do you invalidate cached data on demand?
What makes a route render dynamically?
A loading.tsx or <Suspense> boundary lets the shell flush immediately while slower data streams in after. id: 31112f6b-35e3-42ce-8605-85d2e3f63dff
They became async in Next 15 and must be awaited. This is the most common upgrade break from 14. id: c1d4da39-292c-46c6-8241-914bed8ebdf8
proxy.ts, renamed to make it clear the file is a network-boundary concern, not general app middleware. id: b89e1761-7b29-4d86-941f-8d94cba01938
Route Handlers expose a real HTTP endpoint for external callers; Server Actions are RPC for your own UI. id: 879b33d3-9a13-4683-85c2-920874376b11
14 cached fetch and GET handlers implicitly; 15 turned those off by default; 16 makes caching explicit opt-in. id: 6e385274-c2f9-4209-881a-56e8dc11e801
An opt-in model (cacheComponents: true) where nothing caches unless a function or component is marked cacheable. id: 43818909-a4a9-4a0c-9570-48ca378335c5
Reading request data — cookies, headers, searchParams — or opting out via dynamic = 'force-dynamic'. id: 21ed2d23-ff7f-48e4-b385-8e4fb9134e21
revalidatePath and revalidateTag from a Server Action or Route Handler, with cacheTag marking what to bust. id: d189eb16-3379-474f-940e-f5a7746e8156
What is Partial Prerendering, and where did it land?
What are Instant Navigations (16.3)?
What problem do root params (16.3) solve?
How does error handling work in the App Router?
What are parallel and intercepting routes?
How do you set page metadata?
What is the bundler story in Next 16?
Interview one-liner: what is the App Router's architectural theme?
An opt-in suite — partial prefetching, extracted loading shells, Instant Insights — for SPA-feel routing. id: 0ee4bd31-3505-4894-8400-9e4344ac5493
Serving a static shell with dynamic holes streamed in. It shipped folded into the Cache Components model in 16. id: e3946fed-ed3f-4ef1-aa3c-7230c2162313
error.tsx catches a segment's render errors, global-error wraps the root, notFound() renders 404. id: f09b5d3b-4045-43bb-9f71-1315ca05f623
Reading a root-level param like [lang] from any Server Component, instead of prop-drilling it down the tree. id: 6ab944e9-1bb1-426d-a7a8-dcf7f2e32abe
Export a static metadata object or an async generateMetadata from a layout or page. id: 33f43377-f78a-4f79-9c89-428d9f5a7840
@slot folders render several pages into one layout; (.) and (..) intercept a route to show it as a modal. id: 94dd7854-9bf5-43e8-8afe-a317bee7fc60
Rendering moves to the server by default and caching moves from implicit to explicit, opt-in and per-component.
Turbopack is the default for dev and build; webpack config is deprecated with a temporary --webpack fallback. id: 9bee220e-0bbc-4757-973d-6bf2a9473b5d
Name the four caching layers of the App Router.
What is request memoization?
What is the Data Cache?
What is the Full Route Cache?
What is the Router Cache?
Is fetch cached by default?
What does the 'use cache' directive do?
What do cacheTag and cacheLife add to 'use cache'?
React dedupes identical fetches within a single render pass, so shared components can each fetch what they need. id: a7ef8893-81c9-4394-b0f8-ba63fa142f68
Request memoization, the Data Cache, the Full Route Cache, and the client-side Router Cache. id: ea06e171-c0c8-48ab-adc3-c97f335c593b
The prerendered HTML and RSC payload for a static route, held on the server and served without rendering. id: 11212494-5b2d-4da7-aa11-4aa317c298f2
A persistent server-side store of fetch results that survives requests and deploys until revalidated. id: 934eae2b-099e-43e8-9c80-aa6d6a393fc2
No. Since 15 fetch defaults to no-store; you opt in with force-cache, next.revalidate, or use cache. id: 53dcfceb-ffa4-4a8b-a3b9-06299ceddfa6
An in-memory client cache of RSC payloads for visited and prefetched routes, so back-navigation is instant. id: c159d16a-2e9c-4514-8050-64653f105394
cacheTag labels an entry for targeted invalidation; cacheLife sets how long it stays fresh and stale. id: 19c872cf-615e-45fd-91c9-77ca1299c341
Marks a file, component or function as cacheable, so its result is stored and reused rather than recomputed. id: aa451521-2c38-4943-9c6e-dfe9898743fa
What does the cacheComponents flag change?
revalidatePath vs revalidateTag?
How do you handle on-demand invalidation from a CMS?
What is ISR in App Router terms?
What does the segment export revalidate = 60 mean?
How do you force a route static or dynamic?
What silently makes a route dynamic?
How do you avoid a request waterfall between fetches?
revalidatePath busts everything for a route; tags bust just the entries you labelled, across every route. id: ab6622d9-23da-4b32-aba1-cb9f101c8893
It switches the app to the explicit model: nothing is cached unless you mark it, and dynamic is the default. id: abb3bd9a-58f0-4b11-9999-5ae0bc6c829e
Time-based revalidation of a prerendered route: serve the cached version, regenerate in the background. id: 650de55e-a972-4985-8584-c925cddc310a
Expose a route handler, verify the webhook signature, then call revalidateTag for the affected content tags. id: 0e981e8e-bb42-47fd-8e6e-bd01cfc65fbe
The segment config dynamic = 'force-static' or 'force-dynamic', overriding what Next.js infers. id: c84268bf-fb1c-42b7-ac12-d69cbee29cb1
The route's cached output is considered fresh for 60 seconds, then regenerated on the next request after that. id: c12987b2-3c77-4a1a-b894-38168d644bc2
Start independent fetches together and await them with Promise.all, rather than awaiting each in sequence. id: d983c381-bcb4-4daf-a4a8-01daee5feddc
Reading cookies, headers, searchParams or connection — any request-time input opts the whole segment out. id: 4c628480-1b00-423a-98e1-1a4db8915386
What is the preload pattern?
When do you reach for React's cache() function?
Where does client-side data fetching still belong?
How do you cache a Route Handler response?
What did 16.3 add to the caching story?
What is partial prefetching?
How does the CDN relate to these caches?
Interview one-liner: how would you explain the caching model to a sceptic?
To dedupe non-fetch work like a database query across one render pass, since only fetch is memoized natively. id: 8c1ead4c-5307-4b6c-ae6b-d74681da1985
Kick off a data fetch in the parent before rendering a child, so the request is already in flight on render. id: 78375417-4401-4937-8de3-5ec09d695ba8
Set Cache-Control headers yourself, or use cache inside it; GET handlers stopped caching by default in 15. id: 4ccfdf9d-4ffb-45a7-afb6-e0e15114f9c1
Anything request-specific and interactive — polling, infinite scroll, optimistic UI — via SWR or TanStack Query. id: c5f5d873-da69-429c-87b7-c1db6a691080
Per-link control over how much of a target route to prefetch, instead of all-or-nothing prefetch={true}. id: b4156d56-2bf2-4f36-99b6-a8e86f8fb065
'use cache' gained client-side caching, letting a route serve a prefetched shell before its data arrives. id: c6fc6f69-9293-4bd6-a912-16dad7991ffe
It moved from four implicit layers you fought against to one explicit directive you opt into, per unit of work.
It sits in front of them, caching full responses by URL; a stale CDN entry survives a revalidateTag. id: 85ff2982-2790-4ae7-8fe9-03481770172d
Composition over prop drilling: what's the first tool you reach for?
When do you NOT need a useEffect?
A prop changes and you want the component's state to reset. What's the idiomatic fix?
Why is array index a bad key, and when is it fine?
What does "colocate state" mean, and what's the rule for lifting it?
Controlled vs uncontrolled inputs — when do you pick each?
What are the two main costs of Context, and how do you mitigate them?
Server state vs client state: why treat them differently?
Whenever the value can be derived during render or computed in an event handler. Effects are for synchronising with something outside React — the DOM, a subscription, the network — not for reacting to your own state changes. id: 5ce50e43-231c-4489-8b63-c699e8ce79ba
Pass JSX as children or as a prop instead of threading data down. The component that owns the state renders the leaf and hands it over, so the components in between never see the prop at all. id: 3b3733de-b24f-49db-8389-d4b4d98fb3b2
Index keys make React reuse the wrong instance when items are inserted, removed or reordered, so state and DOM stick to the wrong row. Fine only for a static list that is never reordered and holds no state. id: a9b08119-0a28-477c-ac59-e4577582e9e5
Give the component a key tied to that prop so React remounts it with fresh state. Mirroring the prop into state and resetting it in an effect renders stale values first and is the classic anti-pattern. id: bce9ddb8-a165-4035-8ee3-81211d9f58a3
Controlled when you need to react to every keystroke: live validation, formatting, dependent fields. Uncontrolled with defaultValue plus a ref or FormData when you only care at submit time — cheaper and the default for Actions. id: 6efacdec-267a-4798-b45f-334451780ee4
Keep state in the lowest component that uses it, and lift it only as far as the closest common ancestor of the components that need it. Lifting higher than necessary re-renders half the tree for no reason. id: cdfff9b7-7010-49c0-b442-8245d47d99cc
Server state is a cache of data you do not own — it goes stale and needs fetching, deduping, revalidation and error states, so use RSC or a query library. Client state is UI state you do own, where useState or the URL is enough. id: 9c66eb52-2596-4c77-8de2-59c0ae5849a5
Every consumer re-renders whenever the value identity changes, and consumers become coupled to a provider being present. Split contexts by update frequency, memoise the value, and prefer passing children through over pushing everything into context. id: f6e93796-f76a-4ab7-a015-e6659eddfa00
useState vs useReducer — where's the line?
What makes a good custom hook, and what are the Rules of Hooks?
An effect fetches data and the props change mid-flight. What goes wrong and how do you fix it?
Why does StrictMode run effects twice in development?
useRef vs useState — what belongs in a ref?
When should you still hand-write useMemo, useCallback and memo?
What is an error boundary, and what does it NOT catch?
What does Suspense actually do, and what triggers it?
It names one behaviour, composes other hooks, and returns values rather than JSX. Hooks must be called unconditionally at the top level of a component or another hook — never inside loops, conditions, or callbacks. id: 71cb2ffa-f40e-4964-a2f5-532bac15daa7
Reach for useReducer once several pieces of state change together, or when the next state depends on what happened rather than on one new value. It moves transitions into a single pure function you can test and read in one place. id: e82642cb-4fe7-4886-8444-2c486f4c2f6e
It mounts, unmounts and remounts to surface effects that are not safely repeatable, so a missing or wrong cleanup fails loudly. It is development-only, and the fix is correct cleanup rather than a "has run" guard. id: ee89d004-f770-438a-86eb-0d401f6bbafe
Responses can resolve out of order and the stale one overwrites the fresh one. Fix it in the cleanup function: abort with an AbortController or flip an ignore flag — or hand fetching to a library that already does this. id: dfdd9ee1-bb3b-46b1-a69f-df8d1f421178
For genuinely expensive computations, for stable identities crossing a boundary you do not control such as effect dependencies or a third-party library, and for re-render problems you have actually measured. The React Compiler covers the routine cases. id: da6c1495-1b16-496a-9fb6-3f63cc1af25c
A ref holds a mutable value that does not affect the rendered output: DOM nodes, timer and subscription ids, previous values. Writing to it does not re-render, and you should not read or write it during render. id: ec530534-eb3b-4fbd-ba6e-982c7d1fd9cf
It renders a fallback while something below it suspends — a lazily loaded component, or a promise read with use() or a Suspense-aware data source. On the server it also marks the boundary where streaming can flush. id: 8ac7f30b-1768-4e77-af72-6af244cae02b
A component that catches errors thrown while rendering its subtree and shows a fallback instead of unmounting the app. It does not catch errors in event handlers, async callbacks, or ones thrown by itself. id: 079a4fc6-5a88-44ac-9010-3232fada356b
Server Components vs Client Components: where does the boundary go?
How do you build a form with Server Actions in React 19?
What is the compound component pattern, and when is it worth it?
What does "headless" mean for a UI component, and how do you build one?
How should you type component props in TypeScript today?
You're wrapping a native button. What does the wrapper need to get right?
What accessibility basics does a custom interactive component owe the user?
What are the conventions for testing React components with Testing Library?
Pass an async function to form action. Wrap it in useActionState to get state, formAction and isPending, read the pending state inside children with useFormStatus, and add useOptimistic when you want instant feedback. id: 38eef364-ec5a-4fea-b595-f1bdc986d2a9
Server is the default: data access, secrets and heavy dependencies stay there and ship no JavaScript. Push 'use client' down to the leaves that need state, effects or event handlers, and pass server data in as serialisable props. id: 50dc249f-4a8b-496e-9c0f-e6bcc7d3691d
Behaviour, state and accessibility with no styling: expose a hook or prop getters and let the caller render the markup. It is how Radix, Headless UI and TanStack work, and it has largely replaced render props. id: 9bf2a456-ced1-452e-8366-0e0873802cee
Related parts such as Tabs, TabList and TabPanel share implicit state through context, so the consumer controls the markup and ordering. Worth it when a component has many valid arrangements that would otherwise become a pile of configuration props. id: 8e51b0ce-ddb0-46ef-b7b0-b918b33335cb
Spread the remaining props through, forward ref — a plain prop in React 19 — default type to "button", and merge className instead of overwriting it, typically with clsx plus tailwind-merge. id: 2f17606d-90f5-4886-9422-c60edb36ad5e
Declare a props type and annotate the parameter rather than using React.FC. Inherit native props with ComponentProps<'button'>, type children as ReactNode, and use discriminated unions so impossible prop combinations will not compile. id: 3415e1ca-554d-464d-995d-f3d9dc565581
Query the way a user would — role, then label, then text, with test ids as the last resort — drive interactions with user-event, assert on rendered output rather than state or props, and use findBy queries for anything async.
A real semantic element where one exists, full keyboard operation with visible focus, an accessible name, ARIA state that tracks reality such as aria-expanded, and focus management for overlays including returning focus on close. id: 869efde8-8eb7-49d9-b4a2-5ed3405cf6fe
When did TypeScript 5.8, 5.9, 6.0 and 7.0 ship?
What is TypeScript 7.0, and why is it a landmark release?
Is TypeScript 7 a new language or type system?
How does TypeScript 7 use multiple cores?
What happened to tsc's watch mode and editor support in 7.0?
Which tsconfig defaults changed on the way to 7.0?
Why does "types": [] as a default break so many projects?
What did TypeScript 6.0 deprecate?
It is the compiler and language service ported from JavaScript to Go, released 8 Jul 2026. Microsoft measured 7.7x-11.9x faster builds on real codebases with 6-26% lower memory use. id: 93a025f0-b6df-4153-8773-53d6f611032f
5.8 on 28 Feb 2025, 5.9 on 1 Aug 2025, 6.0 on 23 Mar 2026 and 7.0 on 8 Jul 2026. The 5.x line ran on a roughly 3-month cadence; 6.0 and 7.0 arrived four months apart in 2026. id: 1a9f8837-47fd-4a22-8801-273a713f4749
New --checkers flag (default 4) runs type-checking across parallel workers and --builders parallelises project-reference builds; --singleThreaded turns parallelism off. id: 3ce72215-5be1-46f8-9319-49ceb655f045
No - it is a port, not a redesign. The syntax, type system and checking semantics are the same as 6.0; what changed is the implementation, the supported config surface and the tooling around it. id: c5641be1-503d-4cda-b1df-cd6213ada69e
strict is now true, module defaults to esnext, target to es2025 (6.0), rootDir to the tsconfig's own directory, and types to an empty array. id: f39d0975-4ad7-4cf5-adf3-fa923cf30460
--watch was rebuilt on a Go port of Parcel's file watcher, and the language server was rewritten on LSP - over 80% fewer failing commands and 60% fewer server crashes than 6.0. id: 19cff139-825b-4f1c-8cd9-132385e4d551
target es5, downlevelIteration, moduleResolution node10 and classic, module amd/umd/system/none, baseUrl, outFile, esModuleInterop false, legacy module namespace syntax and import assert. id: 33dc3048-438d-46ff-b841-8da90696bcf5
Previously every package under node_modules/@types was auto-included. Now you must list them explicitly, e.g. "types": ["node"], or globals like process and __dirname stop resolving. id: 0d3a8992-5664-412a-beda-511caf888e3c
What does "ignoreDeprecations": "6.0" do?
Why did TypeScript 6.0 exist at all?
Which options are gone for good in TypeScript 7.0?
How did TypeScript 7 change checking of plain JavaScript files?
Can Vue, Svelte, Angular, Astro or MDX use TypeScript 7 today?
What was tsgo, and what does TypeScript 7 ship as now?
How do you run TypeScript 6 and 7 side by side?
What is planned for TypeScript 7.1, and when?
It is the bridge release: the last JavaScript-based compiler, whose job was to surface 7.0's breaking changes as deprecations while you were still on the familiar codebase. id: 67c35cf7-9d5f-43f9-bc8e-2ec358fcfcf9
It downgrades 6.0's deprecation errors back to warnings so a project can keep building on the old options - an escape hatch for migration, not a long-term setting, since 7.0 removes them outright. id: 04e9a4ea-7122-4511-8789-2eefe56af5bb
JS support was tightened to match TS rules: values can no longer stand in for types, Closure-style annotations are no longer recognised, and postfix ! is unsupported. id: 5299219e-b8dc-4ba5-888a-bfbd8d32de2e
target es5 and downlevelIteration, moduleResolution node10/classic, module amd/umd/systemjs/none, baseUrl, and esModuleInterop or allowSyntheticDefaultImports set to false. id: d9bd7254-8f89-4cc3-82e0-84651025c365
tsgo was the preview executable in the @typescript/native-preview package. Stable 7.0 ships in the normal typescript package and is invoked as tsc. id: 94de8bec-36b1-4514-9c6a-48a8d5f7ea63
Not yet. Embedded-language tooling depends on the compiler API, which is only stabilised in 7.1 - until then those frameworks stay on the 6.0 toolchain. id: a4727286-ba89-414a-8c17-aac9ce14d717
Per the published iteration plan: beta 9 Sep 2026, RC 20 Oct, stable 10 Nov 2026. Headline item is the stable programmatic API, plus ES2026 lib/target and type on import attributes. id: 42b50981-9920-4870-ba9e-fb1b68218d10
Install the @typescript/typescript6 compatibility package, which lets both compilers coexist without name collisions while you migrate parts of a repo. id: 14ce4da3-676e-46d0-b2d2-429a5098d129
Why does the missing programmatic API in 7.0 matter?
What release cadence has the team signalled after 7.0?
What is import defer, added in 5.9?
Why did 5.9 add --module node20 when nodenext exists?
What else did 5.9 bring to everyday DX?
What is --erasableSyntaxOnly (5.8) for?
What return-type bug did 5.8 start catching?
What did 5.8 change about requiring ESM?
A return to the pre-7.0 rhythm: featureful releases roughly every 3-4 months. id: d805fc6e-8fdb-45a2-b5ca-f42115292ecf
Everything built on the old JS compiler API - typed ESLint rules, ts-jest, bundler plugins, framework language tooling - cannot target the Go compiler until 7.1 stabilises that API. id: cadcffef-ab0d-4672-93b4-11d139a00262
nodenext floats: its behaviour shifts as Node evolves. node20 pins the semantics of Node 20 so builds stay reproducible, exactly as node18 did in 5.8. id: c2e93e14-6681-4bfa-a073-3bbaf2aef407
Syntax like import defer * as ns from "./m" loads a module but delays evaluating it until one of its exports is actually touched - a startup-cost optimisation. 5.9 added the type-checking for it. id: 007ee4bd-0a15-4966-af4b-3afac5e73e63
It errors on TypeScript constructs that emit runtime code - enums, namespaces, parameter properties - so the file is valid under Node's type-stripping, where types are simply erased. id: b4dad803-a465-4944-8c30-6bcf09740a42
A much leaner, more prescriptive tsc --init output, MDN-sourced summaries on DOM APIs, and expandable +/- quick-info hovers with a configurable length limit. id: ba71b7d6-4194-48cc-8f50-ff0154573852
Under --module nodenext, require() of an ES module is allowed, matching Node 22. The new --module node18 keeps the older rules for projects still on Node 18.
For a conditional expression in a return statement, each branch is now checked against the declared return type, instead of only the union-ed result. id: a2d80053-92da-48a3-b265-6546c25690a7
unknown vs any vs never - when do you reach for each?
What does satisfies do that a type annotation does not?
How do you get exhaustiveness checking on a discriminated union?
What is a user-defined type guard, and what changed in 5.5?
Explain conditional types and infer in one breath.
What is a mapped type, and what does key remapping add?
Which built-in utility types should be reflexive for you?
interface vs type alias - what actually differs?
satisfies checks a value against a type without widening it, so you keep the literal inference. const routes = {...} satisfies Record<string, Route> validates the shape but keeps the exact keys for autocomplete. id: 57f4a6ed-1dca-44c8-b5d1-25c8ea740e14
any switches checking off and infects everything it touches; unknown is the safe top type you must narrow before use; never is the empty type returned by functions that never return and left over from exhaustive narrowing. Type external input as unknown, never any. id: b8d77ea2-5677-4eb2-bd9a-d40594866c50
A function returning x is Foo that narrows at call sites. Since 5.5 TypeScript infers those predicates for simple functions, so a filter callback like x => x !== null can narrow without the manual annotation. id: ffb5b613-0135-4442-b78d-58d48c085441
In the default branch assign the value to never: const _x: never = value. If a new variant is added the assignment stops compiling, so the switch fails at build time rather than silently falling through. id: f86ebffe-788b-4f48-bc68-395d13f69b00
{ [K in keyof T]: ... } rebuilds a type key by key; as in the key position renames or drops keys, e.g. { [K in keyof T as `get${Capitalize<K & string>}`]: () => T[K] } to generate getters. id: 0a438d6f-3b64-4d99-9279-71e0ea1312ee
T extends U ? A : B picks a branch per type, and infer names a type captured during that match: type El<T> = T extends (infer U)[] ? U : never. Over a union the conditional distributes member by member. id: c8183ba5-ee71-40d3-9a7e-03324002865a
Interfaces support declaration merging and are used for augmenting other modules' types; type aliases can express unions, tuples, conditionals and mapped types. Use interface for object contracts, type for anything computed. id: d1662558-132b-47f2-936b-d997d36c7929
Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, ReturnType, Parameters, Awaited. Most are a mapped or conditional type you could write yourself in one line. id: 674406a5-ba7e-4f01-a52f-872bdefd0aad
What is structural typing, and where does it bite?
How do you get nominal typing in a structural system?
keyof, typeof and T[K] - what does each give you?
What does as const do?
What is a const type parameter, and why does it matter?
Template literal types - give a real use.
Why can index signatures lie, and what fixes it?
When are function overloads the right tool?
Brand the type: type UserId = string & { readonly __brand: 'UserId' }. A plain string no longer assigns, so you cannot pass an OrderId where a UserId belongs - useful for ids, currency and unvalidated input. id: 87669230-5bc8-49b7-9816-767f460a3f4c
Compatibility is by shape, not by name, so any object with the right members fits. The exception is excess property checking on fresh object literals, which is why an inline literal errors but the same value assigned via a variable does not. id: cefb6c2b-3491-4c44-aaaf-532f235bac87
It makes an object or array deeply readonly and infers literal types instead of widened ones, so ['a','b'] as const becomes readonly ['a','b'] - the usual way to derive a union of literals from a value. id: 84378703-2c28-4994-ad81-6aca8a13a226
typeof lifts a value into its type, keyof gives the union of a type's keys, and T[K] is indexed access. Together: typeof config, keyof typeof config, and config[keyof typeof config] for the union of its values. id: 0f71b44b-074f-4b71-80af-dd80460fbb46
They build string types from other types: type Ev = `on${Capitalize<'click' | 'focus'>}` gives 'onClick' | 'onFocus'. Common for event names, route paths and CSS-in-TS keys. id: c514b9eb-ce9f-46a6-81a9-2cbb2f1527e0
<const T> on a generic makes call-site arguments infer as literals without the caller writing as const, so a helper can return precise literal types from a plain inline array or object. id: 8c015200-4cfb-432c-9d7d-94315d7e40c7
When the return type depends on the argument shape in a way a union cannot express. Otherwise prefer a union parameter or a generic - overloads are unchecked against each other and easy to get wrong. id: 76539078-1131-4e81-a6f5-9dbfd843bfb1
Record<string, T> claims every key exists, so obj['missing'] types as T but is at runtime undefined. --noUncheckedIndexedAccess adds | undefined to indexed reads and forces you to check. id: 2b610f9f-f8ca-4723-aa33-9915ebb459ed
Why do people avoid enums, and what replaces them?
What is strictFunctionTypes actually protecting you from?
Why import type, and what does isolatedModules demand?
What is declaration merging / module augmentation for?
How should types cross a network boundary?
ts-ignore vs ts-expect-error - which and why?
What is NoInfer<T> for?
You inherit a large JS codebase. How do you get it to strict TS?
It checks function parameters contravariantly, so a handler taking a narrower parameter cannot be assigned where a wider one is expected. Method-shorthand parameters stay bivariant, which is why the same bug slips through on interfaces declared with method syntax. id: 1a508d35-3d3e-4b6b-b38a-db9fc4ee6c05
Enums emit runtime code, break under Node's type-stripping and --erasableSyntaxOnly, and numeric enums accept any number. Use a const object plus typeof obj[keyof typeof obj], or a plain string union. id: c467dcdd-5d9c-4b6e-954a-944ac94d309f
declare module '...' reopens another package's types to add your own - extending Express's Request, next-auth's Session, or adding keys to ProcessEnv - without forking the package. id: c864349b-ef3b-4ac2-b06b-623a5bcbc602
import type marks an import as erasable so bundlers and single-file transpilers do not keep a runtime import. isolatedModules requires every file to be transpilable alone, which is what Next.js, esbuild and SWC do. id: b10e2203-0fb7-4df1-8a31-a3fa3352d081
@ts-expect-error, because it errors when the line stops failing, so the suppression gets cleaned up. @ts-ignore stays silent forever and hides the next real bug on that line. id: 840f1859-3b08-4bbf-9516-77414d90ff04
Do not assert. Parse at the edge with a runtime validator (zod, valibot) and infer the static type from the schema, so one definition guards both runtime and compile time. as Response is a lie the compiler cannot check. id: 2c196974-34da-4687-a702-427ff12c090e
Turn on allowJs and checkJs with strict off, rename leaf modules first, type the boundaries (API, config, shared models) before internals, then enable strict flags one at a time - strictNullChecks last and loudest. id: 0df5f104-fd37-4ffb-88f3-f2e41ae9c16e
It blocks a type parameter from being inferred from that position, so one argument drives inference and another is only checked against it - e.g. a default value that must match the options array, not widen it. id: 1caa3471-733e-413e-9a61-2d8265e4b2ef
How do you type a React component's props well?
useState and useRef - where does inference fail?
How do you write a generic React component?
Why is useReducer a showcase for discriminated unions?
How do you type event handlers without guessing?
What does the Server/Client boundary mean for types?
How do you get end-to-end type safety from route to component?
Which strict flags do you turn on beyond strict: true?
useState(null) infers null, so pass the generic: useState<User | null>(null). For DOM refs use useRef<HTMLInputElement>(null) which gives the readonly ref React assigns; useRef<number>(0) gives a mutable box. id: daed2ef5-f046-4618-b086-6c505f5d99ea
Declare an explicit props type and destructure; use React.ReactNode for renderable children and ComponentProps<'button'> to inherit native props. Avoid React.FC - it adds little and complicates generics. id: 7de8559c-2da5-4c68-ab61-8272d2576db3
Actions are a union tagged by type, so the reducer's switch narrows the payload per case and a never default makes new actions a compile error - a state machine the compiler checks for you. id: d6c62020-f2e1-4e01-b32f-cc23c458e774
Type the props with a parameter and let inference flow from the props: function List<T>({ items, render }: { items: T[]; render: (item: T) => ReactNode }). The caller gets T inferred from items. id: 587d069c-f13d-4f8a-b455-8efe4f1debf9
Anything passed from a Server Component to a Client Component must be serializable, so the type system will let you pass a function or Date shape that fails at runtime. Keep the boundary props to plain data. id: 08393373-a5c4-4ff0-8847-8ccfdd974d57
Take the type from the element: React.ChangeEvent<HTMLInputElement>, React.MouseEvent<HTMLButtonElement>. Better still, type the handler by the prop - ComponentProps<'input'>['onChange'] - and let the parameter infer. id: d6fc881a-4eb2-4fd8-a8d3-755e7b8fae4d
noUncheckedIndexedAccess, exactOptionalPropertyTypes and noImplicitOverride are not in the strict bundle. Say why you would add them - and why exactOptionalPropertyTypes is the one that breaks the most existing code.
Define the model once, derive everything else: infer the response type from the schema or handler, export it, and have the client import that type instead of redeclaring it. Duplicate interfaces are how drift starts. id: e074cdb9-3b1f-4aea-91d6-e3b1b2a0b20a