{"checkpoints":{"s-at-1":[{"q":"<p>A reviewer worries that the card number reaches <code dir=\"ltr\">saveAddress</code>. What is true?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Address</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#953800;--shiki-dark:#FFA657\">line1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; </span><span style=\"color:#953800;--shiki-dark:#FFA657\">city</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> saveAddress</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">a</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Address</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) { </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* sends a to the address service */</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> form</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { line1: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'12 Nile St'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, city: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Cairo'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, cardNumber: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'4242 4242 4242 4242'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">saveAddress</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(form);</span></span></code></pre></div>\n","options":[{"text":"It fails to compile, because <code dir=\"ltr\">cardNumber</code> is an excess property.","why":"Excess property checks only apply to fresh object literals. <code dir=\"ltr\">form</code> is a variable, so the extra field is allowed."},{"text":"TypeScript removes <code dir=\"ltr\">cardNumber</code> before the call, because <code dir=\"ltr\">Address</code> does not declare it.","why":"Types are erased; they never add or remove properties at runtime."},{"text":"It compiles only if you write <code dir=\"ltr\">form as Address</code>.","why":"No assertion is needed. Structural typing already accepts <code dir=\"ltr\">form</code>, which is exactly the risk."},{"text":"It compiles, and the whole object, card number included, is passed at runtime; copy the fields you need explicitly.","why":"Correct. Structural typing allows extra properties, so the only safe fix is to build a new object with <code dir=\"ltr\">line1</code> and <code dir=\"ltr\">city</code>."}],"answer":3},{"q":"<p><code dir=\"ltr\">quantityInStock</code> is <code dir=\"ltr\">null</code> while stock is being checked and <code dir=\"ltr\">0</code> when an item is sold out. Which change makes this label correct?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> stockLabel</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">quantityInStock</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> number</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> |</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> null</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">quantityInStock) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">return</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Checking stock…'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> quantityInStock </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">===</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ?</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Sold out'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> `${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">quantityInStock</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">} left`</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"Replace <code dir=\"ltr\">!quantityInStock</code> with <code dir=\"ltr\">quantityInStock === null</code>.","why":"Correct. The truthiness check also catches <code dir=\"ltr\">0</code>, so ‘Sold out’ is unreachable. Comparing with <code dir=\"ltr\">null</code> keeps the two meanings apart."},{"text":"Add <code dir=\"ltr\">if (typeof quantityInStock === 'number')</code> after the first line.","why":"After the first line <code dir=\"ltr\">0</code> has already returned ‘Checking stock…’; a later check cannot rescue it."},{"text":"Write <code dir=\"ltr\">quantityInStock!</code> in the comparison.","why":"A non-null assertion changes only the type, not the runtime path. The <code dir=\"ltr\">0</code> still takes the first branch."},{"text":"Remove the <code dir=\"ltr\">: string</code> return type so TypeScript infers it.","why":"The return type is not the problem; the truthiness check is."}],"answer":0},{"q":"<p>Cartwheel adds payments. A pending payment has no capture id; a captured one always has <code dir=\"ltr\">captureId</code>; a refunded one always has <code dir=\"ltr\">captureId</code>, <code dir=\"ltr\">refundedAt</code> and <code dir=\"ltr\">refundCents</code>. Which type makes the impossible combinations fail to compile?</p>","options":[{"text":"<code dir=\"ltr\">{ status: 'pending' | 'captured' | 'refunded'; captureId?: string; refundedAt?: string; refundCents?: number }</code>","why":"Optional fields are independent of <code dir=\"ltr\">status</code>, so a refunded payment without <code dir=\"ltr\">refundCents</code> still compiles."},{"text":"<code dir=\"ltr\">{ status: string; details: Record&lt;string, unknown&gt; }</code>","why":"This accepts any status and any details, so it prevents nothing and forces casts everywhere."},{"text":"A union of three object types, each with a literal <code dir=\"ltr\">status</code> and exactly the fields that state has, all required.","why":"Correct. Each variant carries its own required data, and the literal <code dir=\"ltr\">status</code> lets narrowing find the right one."},{"text":"<code dir=\"ltr\">Partial&lt;{ status: string; captureId: string; refundedAt: string; refundCents: number }&gt;</code>","why":"Making every field optional allows even more impossible states than the original."}],"answer":2},{"q":"<p>What is <code dir=\"ltr\">ShippingMethod</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> SHIPPING_FEES</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { standard: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">499</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, express: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1299</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">satisfies</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Record</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">number</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> ShippingMethod</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> keyof</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> typeof</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> SHIPPING_FEES</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">string</code>, because the object was checked against <code dir=\"ltr\">Record&lt;string, number&gt;</code>","why":"That is what an annotation would give you. <code dir=\"ltr\">satisfies</code> checks the object but keeps its inferred type."},{"text":"<code dir=\"ltr\">'standard' | 'express'</code>","why":"Correct. The inferred type has exactly the two keys written, so <code dir=\"ltr\">keyof</code> gives their literal names."},{"text":"<code dir=\"ltr\">number</code>, the type of the values","why":"<code dir=\"ltr\">keyof</code> gives the property names, not the values; the values would be <code dir=\"ltr\">(typeof SHIPPING_FEES)[ShippingMethod]</code>."},{"text":"<code dir=\"ltr\">'standard' | 'express' | string</code>","why":"There is no index signature in the inferred type, so <code dir=\"ltr\">string</code> is not part of the key union."}],"answer":1},{"q":"<p>A <code dir=\"ltr\">switch (order.status)</code> has <code dir=\"ltr\">case 'canceled':</code> with one L, and it never matches. Which change turns that typo into a compile error?</p>","options":[{"text":"Add a <code dir=\"ltr\">default:</code> branch that logs unknown statuses.","why":"That helps at runtime, but the compiler still accepts the misspelled case."},{"text":"Annotate <code dir=\"ltr\">order</code> as <code dir=\"ltr\">any</code> so TypeScript checks each case.","why":"<code dir=\"ltr\">any</code> turns checking off; it would hide the typo even more."},{"text":"Rewrite the <code dir=\"ltr\">switch</code> as an <code dir=\"ltr\">if</code>/<code dir=\"ltr\">else</code> chain.","why":"With a <code dir=\"ltr\">string</code> status, <code dir=\"ltr\">=== 'canceled'</code> compiles just as happily as the <code dir=\"ltr\">case</code>."},{"text":"Type <code dir=\"ltr\">status</code> as the union of the five literal statuses instead of <code dir=\"ltr\">string</code>.","why":"Correct. Against a literal union, <code dir=\"ltr\">case 'canceled':</code> is reported as not comparable to <code dir=\"ltr\">OrderStatus</code>."}],"answer":3}],"s-at-2":[{"q":"<p>Which signature lets <code dir=\"ltr\">firstWhere(orders, (o) =&gt; o.status === 'shipped')</code> return <code dir=\"ltr\">Order | undefined</code>, and <code dir=\"ltr\">firstWhere(products, …)</code> return <code dir=\"ltr\">Product | undefined</code>, with <code dir=\"ltr\">o</code> typed in the callback?</p>","options":[{"text":"<code dir=\"ltr\">function firstWhere&lt;T&gt;(items: T[], predicate: (item: T) =&gt; boolean): T | undefined</code>","why":"Correct. <code dir=\"ltr\">T</code> is inferred from <code dir=\"ltr\">items</code>, then gives the callback its parameter type and the result its type."},{"text":"<code dir=\"ltr\">function firstWhere(items: unknown[], predicate: (item: unknown) =&gt; boolean): unknown</code>","why":"Without a type parameter, the callback’s <code dir=\"ltr\">o</code> is <code dir=\"ltr\">unknown</code> and so is the result; callers would have to cast."},{"text":"<code dir=\"ltr\">function firstWhere&lt;T&gt;(items: unknown[], predicate: (item: T) =&gt; boolean): T | undefined</code>","why":"<code dir=\"ltr\">T</code> now has no inference site except the unannotated callback, so it ends up <code dir=\"ltr\">unknown</code>."},{"text":"<code dir=\"ltr\">function firstWhere(items: any[], predicate: (item: any) =&gt; boolean): any</code>","why":"This compiles everywhere and checks nothing; typos in the callback go unnoticed."}],"answer":0},{"q":"<p>What is the type of <code dir=\"ltr\">t.value</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> tag</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">value</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { value };</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> t</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> tag</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'shipped'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">'shipped'</code>","why":"The literal would survive if <code dir=\"ltr\">T</code> were constrained to <code dir=\"ltr\">string</code> or declared <code dir=\"ltr\">const</code>. Here it is nested in an object and widens."},{"text":"<code dir=\"ltr\">unknown</code>","why":"TypeScript found a candidate, the string argument, so it does not fall back to <code dir=\"ltr\">unknown</code>."},{"text":"<code dir=\"ltr\">any</code>","why":"Inference never produces <code dir=\"ltr\">any</code> from a string literal argument."},{"text":"<code dir=\"ltr\">string</code>","why":"Correct. <code dir=\"ltr\">T</code> is unconstrained and appears inside the returned object, so the literal candidate is widened."}],"answer":3},{"q":"<p><code dir=\"ltr\">setDefault(['standard', 'express'], 'overnight')</code> should be rejected because <code dir=\"ltr\">'overnight'</code> is not one of the options. Which signature does that?</p>","options":[{"text":"<code dir=\"ltr\">function setDefault&lt;const T&gt;(options: T[], fallback: T)</code>","why":"<code dir=\"ltr\">fallback</code> is still an inference site, so <code dir=\"ltr\">'overnight'</code> is added to <code dir=\"ltr\">T</code> instead of being checked."},{"text":"<code dir=\"ltr\">function setDefault&lt;T extends string&gt;(options: T[], fallback: T)</code>","why":"The constraint keeps the literals, but <code dir=\"ltr\">fallback</code> still contributes a candidate, so <code dir=\"ltr\">T</code> grows to include <code dir=\"ltr\">'overnight'</code>."},{"text":"<code dir=\"ltr\">function setDefault&lt;T extends string&gt;(options: T[], fallback: NoInfer&lt;T&gt;)</code>","why":"Correct. The constraint keeps the options as literals, and <code dir=\"ltr\">NoInfer</code> makes <code dir=\"ltr\">fallback</code> check-only."},{"text":"<code dir=\"ltr\">function setDefault&lt;T&gt;(options: T[], fallback: NoInfer&lt;T&gt;)</code>","why":"Without a primitive constraint, the array is inferred as <code dir=\"ltr\">string[]</code>, so any string passes the check."}],"answer":2},{"q":"<p>Callers of Cartwheel’s client write <code dir=\"ltr\">api.get&lt;Order&gt;('/orders/1042')</code> everywhere, and last week someone wrote <code dir=\"ltr\">api.get&lt;Order[]&gt;('/orders/1042')</code>. What is the best fix?</p>","options":[{"text":"Key the client by a route map type, so the response type is looked up from the route and callers pass no type argument.","why":"Correct. The route becomes the only inference site, and a wrong response type is no longer something a caller can write."},{"text":"Add an ESLint rule that requires a type argument on every <code dir=\"ltr\">get</code> call.","why":"That enforces writing a type argument, not writing the right one; the bug was a wrong type argument."},{"text":"Change the default type parameter of <code dir=\"ltr\">get</code> to <code dir=\"ltr\">any</code>.","why":"That removes the remaining checking and makes wrong usage even quieter."},{"text":"Make <code dir=\"ltr\">get</code> return <code dir=\"ltr\">unknown</code> and let each caller cast with <code dir=\"ltr\">as</code>.","why":"This moves the same unchecked claim into an <code dir=\"ltr\">as</code> at every call site; it is safer than <code dir=\"ltr\">any</code> but not a fix."}],"answer":0},{"q":"<p><code dir=\"ltr\">function useQuery&lt;TData, TKey extends string&gt;(key: TKey, fetcher: () =&gt; Promise&lt;TData&gt;)</code> is called as <code dir=\"ltr\">useQuery&lt;Order&gt;('order-1042', loadOrder)</code> and fails with “Expected 2 type arguments, but got 1”. What is the best fix at the call site?</p>","options":[{"text":"Write <code dir=\"ltr\">useQuery&lt;Order, string&gt;(…)</code> everywhere.","why":"It compiles, but the key loses its literal type and every call site gets noisier."},{"text":"Remove <code dir=\"ltr\">&lt;Order&gt;</code> and let both type parameters be inferred, <code dir=\"ltr\">TData</code> from <code dir=\"ltr\">loadOrder</code>’s return type.","why":"Correct. Explicit type arguments are all or nothing; with none, TypeScript infers both from the arguments."},{"text":"Wrap the key in <code dir=\"ltr\">NoInfer</code>.","why":"<code dir=\"ltr\">NoInfer</code> controls inference sites; it does not make explicit type arguments partial."},{"text":"Cast the call result to <code dir=\"ltr\">any</code>.","why":"The error is about the type arguments of the call, which a cast on the result cannot fix."}],"answer":1}],"s-at-3":[{"q":"<p>What is <code dir=\"ltr\">F</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Flags</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { [</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> in</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> keyof</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> as</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">extends</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> boolean</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ?</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> K</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> never</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> F</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Flags</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;{ </span><span style=\"color:#953800;--shiki-dark:#FFA657\">giftWrap</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> boolean</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; </span><span style=\"color:#953800;--shiki-dark:#FFA657\">note</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; </span><span style=\"color:#953800;--shiki-dark:#FFA657\">express</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> boolean</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }>;</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">{ giftWrap: boolean; note: never; express: boolean }</code>","why":"Mapping a key to <code dir=\"ltr\">never</code> in an <code dir=\"ltr\">as</code> clause removes it entirely; it does not keep it with type <code dir=\"ltr\">never</code>."},{"text":"<code dir=\"ltr\">'giftWrap' | 'express'</code>","why":"That would be the result of indexing the mapped type with <code dir=\"ltr\">[keyof T]</code>. This type keeps the object shape."},{"text":"<code dir=\"ltr\">{ note: string }</code>","why":"The condition keeps boolean properties and drops the rest, not the other way round."},{"text":"<code dir=\"ltr\">{ giftWrap: boolean; express: boolean }</code>","why":"Correct. The <code dir=\"ltr\">as</code> clause sends non-boolean keys to <code dir=\"ltr\">never</code>, which drops them from the result."}],"answer":3},{"q":"<p>What is <code dir=\"ltr\">X</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"5\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> IdOf</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> extends</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#953800;--shiki-dark:#FFA657\">id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> infer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> I</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> I</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> never</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> X</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> IdOf</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;{ </span><span style=\"color:#953800;--shiki-dark:#FFA657\">id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> number</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">|</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#953800;--shiki-dark:#FFA657\">id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">|</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#953800;--shiki-dark:#FFA657\">name</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }>;</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">number | string</code>","why":"Correct. The conditional distributes over the union: two members capture their <code dir=\"ltr\">id</code> type, and the third becomes <code dir=\"ltr\">never</code> and disappears."},{"text":"<code dir=\"ltr\">never</code>, because the union as a whole has no common <code dir=\"ltr\">id</code>","why":"That would be the non-distributive result. A naked type parameter makes the check run per member."},{"text":"<code dir=\"ltr\">number</code>, from the first member only","why":"Every member is processed, and the results are joined."},{"text":"<code dir=\"ltr\">unknown</code>, because <code dir=\"ltr\">infer</code> cannot capture from a union","why":"<code dir=\"ltr\">infer</code> works per member after distribution, so each capture is precise."}],"answer":0},{"q":"<p>What is <code dir=\"ltr\">`on${Capitalize&lt;'shipped' | 'cancelled'&gt;}`</code>?</p>","options":[{"text":"<code dir=\"ltr\">'onshipped' | 'oncancelled'</code>","why":"<code dir=\"ltr\">Capitalize</code> upper-cases the first letter of each member before it is joined to <code dir=\"ltr\">on</code>."},{"text":"<code dir=\"ltr\">`on${string}`</code>","why":"With literal members inside, the template expands to concrete strings rather than a pattern."},{"text":"<code dir=\"ltr\">'onShipped' | 'onCancelled'</code>","why":"Correct. The union distributes through the template, and each member is capitalised."},{"text":"<code dir=\"ltr\">'onShipped | Cancelled'</code>","why":"Unions are not joined into one string; each member produces its own string literal."}],"answer":2},{"q":"<p>What is <code dir=\"ltr\">Draft&lt;{ readonly id: number; status: string }&gt;</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"6\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Draft</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-readonly</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> in</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> keyof</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] };</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">{ readonly id: number; status: string }</code>, unchanged","why":"The <code dir=\"ltr\">-readonly</code> and <code dir=\"ltr\">?</code> modifiers change both properties."},{"text":"<code dir=\"ltr\">{ id: number; status: string }</code>","why":"<code dir=\"ltr\">-readonly</code> is applied, but <code dir=\"ltr\">?</code> also makes every property optional."},{"text":"<code dir=\"ltr\">{ readonly id?: number; status?: string }</code>","why":"The <code dir=\"ltr\">-</code> prefix removes <code dir=\"ltr\">readonly</code> from <code dir=\"ltr\">id</code>; only the optional modifier is added."},{"text":"<code dir=\"ltr\">{ id?: number; status?: string }</code>","why":"Correct. <code dir=\"ltr\">-readonly</code> strips the readonly modifier and <code dir=\"ltr\">?</code> makes each property optional."}],"answer":3},{"q":"<p>What is <code dir=\"ltr\">ElementOf&lt;readonly string[]&gt;</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"7\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> ElementOf</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> extends</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">infer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> E</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> E</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">string</code>","why":"A <code dir=\"ltr\">readonly string[]</code> is not assignable to the mutable pattern <code dir=\"ltr\">(infer E)[]</code>, so the true branch is not taken."},{"text":"<code dir=\"ltr\">readonly string[]</code>","why":"Correct. Readonly arrays lack mutating methods, so they do not match a mutable array pattern; use <code dir=\"ltr\">readonly (infer E)[]</code> in the pattern."},{"text":"<code dir=\"ltr\">never</code>","why":"The false branch returns <code dir=\"ltr\">T</code> itself, not <code dir=\"ltr\">never</code>."},{"text":"<code dir=\"ltr\">unknown</code>","why":"Nothing here produces <code dir=\"ltr\">unknown</code>; the pattern simply fails to match."}],"answer":1}],"s-at-4":[{"q":"<p>What is wrong with this code?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"8\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> JSON</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">parse</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(body).orderId </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> OrderId</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">cancelOrder</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(id);</span></span></code></pre></div>\n","options":[{"text":"Nothing; the brand is checked when <code dir=\"ltr\">cancelOrder</code> runs.","why":"Brands do not exist at runtime, so nothing checks anything when the function runs."},{"text":"<code dir=\"ltr\">JSON.parse</code> always returns a string, so <code dir=\"ltr\">orderId</code> is a string.","why":"<code dir=\"ltr\">JSON.parse</code> returns whatever the JSON contains; here the problem is the unchecked cast."},{"text":"The cast brands a value nobody validated; parse it with the smart constructor, such as <code dir=\"ltr\">toOrderId(…)</code>, instead.","why":"Correct. A brand is only meaningful when it is applied after validation, in one place."},{"text":"Branded types cannot be used with values that came from JSON.","why":"They can, as long as the JSON value goes through a validating constructor first."}],"answer":2},{"q":"<p>A caller of <code dir=\"ltr\">charge(): Result&lt;Receipt, PaymentError&gt;</code> writes <code dir=\"ltr\">if (result.error) showError(result.error)</code>. What happens?</p>","options":[{"text":"It does not compile, because <code dir=\"ltr\">error</code> only exists on the failure member; check <code dir=\"ltr\">result.ok</code> first.","why":"Correct. Property access on a union requires the property on every member, so you narrow with the discriminant."},{"text":"It compiles and works, because <code dir=\"ltr\">error</code> is <code dir=\"ltr\">undefined</code> on success.","why":"The success member does not declare <code dir=\"ltr\">error</code> at all, so TypeScript rejects reading it before narrowing."},{"text":"It compiles, but the condition is always false.","why":"It does not compile in the first place."},{"text":"It throws at runtime when the result is a success.","why":"Reading a missing property gives <code dir=\"ltr\">undefined</code> in JavaScript, but TypeScript stops the code before it ever runs."}],"answer":0},{"q":"<p>Cartwheel’s server renders the initial cart into the page as JSON. Bad data there means a broken deploy, not something a customer can fix. How should the client handle it?</p>","options":[{"text":"A type predicate in an <code dir=\"ltr\">if</code>, falling back to an empty cart when it fails.","why":"Silently showing an empty cart hides a deploy bug from everyone, including your monitoring."},{"text":"<code dir=\"ltr\">const cart = JSON.parse(text) as Cart</code>.","why":"An unchecked cast lets a broken deploy surface as confusing errors far from the cause."},{"text":"A parser returning a <code dir=\"ltr\">Result</code>, with a retry when it fails.","why":"Retrying cannot fix data that the server rendered wrong; this is not an expected, recoverable failure."},{"text":"An assertion function called once at startup that throws a clear error, which your error reporting picks up.","why":"Correct. Bad data here is a bug, so failing loudly at the boundary is the right behaviour."}],"answer":3},{"q":"<p>What is the problem with this emitter method?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"9\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">on</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(event: keyof Events, handler: (</span><span style=\"color:#953800;--shiki-dark:#FFA657\">payload</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Events</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">keyof</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Events</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> void</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">): </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">void</span></span></code></pre></div>\n","options":[{"text":"Arrow functions cannot be passed as handlers.","why":"Any function with a compatible signature can be passed; the issue is which signature that is."},{"text":"The handler’s payload is the union of every event’s payload, not the payload of the event being subscribed to.","why":"Correct. Without a type parameter <code dir=\"ltr\">K</code>, nothing links the name to its payload. Use <code dir=\"ltr\">on&lt;K extends keyof Events&gt;(event: K, handler: (payload: Events[K]) =&gt; void)</code>."},{"text":"Event names widen to <code dir=\"ltr\">string</code>, so typos are accepted.","why":"<code dir=\"ltr\">keyof Events</code> is a union of the event names, so typos are still rejected; the payload is what is lost."},{"text":"Nothing; this is the recommended signature.","why":"It compiles, but every handler must narrow a union payload that has no discriminant to narrow on."}],"answer":1},{"q":"<p>You add <code dir=\"ltr\">'on-hold'</code> to <code dir=\"ltr\">OrderStatus</code>. Which lookup table fails to compile until it gets an <code dir=\"ltr\">'on-hold'</code> entry?</p>","options":[{"text":"<code dir=\"ltr\">const LABELS = { … } satisfies Record&lt;OrderStatus, string&gt;</code>","why":"Correct. <code dir=\"ltr\">satisfies</code> checks the object against the full record, so a missing key is an error."},{"text":"<code dir=\"ltr\">const LABELS: Partial&lt;Record&lt;OrderStatus, string&gt;&gt; = { … }</code>","why":"<code dir=\"ltr\">Partial</code> makes every key optional, so a missing status is allowed."},{"text":"<code dir=\"ltr\">const LABELS: Record&lt;string, string&gt; = { … }</code>","why":"Any string keys are allowed, so the table has no idea which statuses exist."},{"text":"<code dir=\"ltr\">const LABELS = { … } as Record&lt;OrderStatus, string&gt;</code>","why":"An assertion only checks that the types overlap, so a missing key is not reported."}],"answer":0}],"s-at-5":[{"q":"<p>A script run with <code dir=\"ltr\">node checkout.ts</code> (Node’s built-in type stripping) contains <code dir=\"ltr\">enum Channel { Web = 'web' }</code> and fails at startup. Which compiler flag would have flagged the enum during <code dir=\"ltr\">tsc</code>?</p>","options":[{"text":"<code dir=\"ltr\">isolatedModules</code>","why":"It catches constructs that need cross-file information, such as re-exporting a type without <code dir=\"ltr\">type</code>, but it allows enums."},{"text":"<code dir=\"ltr\">verbatimModuleSyntax</code>","why":"It governs how imports and exports are emitted; enums are still allowed."},{"text":"<code dir=\"ltr\">erasableSyntaxOnly</code>","why":"Correct. It rejects syntax that generates runtime code, such as enums, which type stripping cannot handle."},{"text":"<code dir=\"ltr\">noEmit</code>","why":"It stops <code dir=\"ltr\">tsc</code> writing files; it adds no checks."}],"answer":2},{"q":"<p>Why can this charge run while the cart is unlocked?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"10\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">async</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> pay</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">cartId</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> string</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">needsLock</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> boolean</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (needsLock) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    using</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> lock</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> acquireCartLock</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cartId);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  await</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> charge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cartId);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">using</code> is not allowed in <code dir=\"ltr\">async</code> functions.","why":"It is allowed; for asynchronous cleanup you would use <code dir=\"ltr\">await using</code>, but that is not the issue here."},{"text":"It should be <code dir=\"ltr\">await using</code>, because the function is <code dir=\"ltr\">async</code>.","why":"<code dir=\"ltr\">await using</code> is for resources with async disposal; the lock’s scope is the real problem."},{"text":"The lock is never released.","why":"It is released, but too early."},{"text":"The lock is disposed at the end of the <code dir=\"ltr\">if</code> block, before <code dir=\"ltr\">charge</code> runs.","why":"Correct. <code dir=\"ltr\">using</code> is scoped to its block; declare it in the block that also contains the charge."}],"answer":3},{"q":"<p><code dir=\"ltr\">interface Window { dataLayer: unknown[] }</code> sits at the top level of <code dir=\"ltr\">src/analytics.ts</code>, which also has imports. <code dir=\"ltr\">window.dataLayer</code> is still an error. Why?</p>","options":[{"text":"In a module file, a top-level interface is local to that module; wrap it in <code dir=\"ltr\">declare global { … }</code> to merge with the global <code dir=\"ltr\">Window</code>.","why":"Correct. Files with imports or exports are modules, and only <code dir=\"ltr\">declare global</code> reaches the global scope from inside one."},{"text":"<code dir=\"ltr\">Window</code> is a built-in type and cannot be extended.","why":"It can; extending <code dir=\"ltr\">Window</code> through declaration merging is common."},{"text":"It must be a <code dir=\"ltr\">type</code> alias instead of an interface.","why":"Type aliases never merge, so a <code dir=\"ltr\">type</code> would not extend <code dir=\"ltr\">Window</code> either."},{"text":"Interface merging only works in <code dir=\"ltr\">.d.ts</code> files.","why":"Merging works in <code dir=\"ltr\">.ts</code> files too; what matters is whether the declaration is in the global scope."}],"answer":0},{"q":"<p>A monorepo has six packages type-checked as one big program, and every small change re-checks all of them for 90 seconds. Which change helps most?</p>","options":[{"text":"Turn off <code dir=\"ltr\">strict</code> in the slowest package.","why":"That reduces checking quality, and <code dir=\"ltr\">strict</code> is rarely the main cost."},{"text":"Split it into project references (<code dir=\"ltr\">composite: true</code> per package, <code dir=\"ltr\">tsc -b</code> at the root), so unchanged packages are not re-checked.","why":"Correct. Each package is built once and its declarations reused, so a change only re-checks what depends on it."},{"text":"Set <code dir=\"ltr\">skipLibCheck: false</code> to catch more problems early.","why":"That makes checking slower, not faster."},{"text":"Merge all packages into one <code dir=\"ltr\">src</code> folder.","why":"One larger program has the same problem with fewer boundaries to cache."}],"answer":1},{"q":"<p>A <code dir=\"ltr\">.js</code> file starts with <code dir=\"ltr\">// @ts-check</code> and declares <code dir=\"ltr\">/** @param {Order} order */ function ship(order) { … }</code>. What does TypeScript do with it (with <code dir=\"ltr\">allowJs</code> on)?</p>","options":[{"text":"Nothing, until the file is renamed to <code dir=\"ltr\">.ts</code>.","why":"The comment opts the JavaScript file into checking without renaming it."},{"text":"It checks the file only if <code dir=\"ltr\">checkJs</code> is also <code dir=\"ltr\">true</code> in tsconfig.","why":"<code dir=\"ltr\">checkJs</code> turns checking on for all JS files; <code dir=\"ltr\">// @ts-check</code> does it for one file regardless."},{"text":"It checks only the JSDoc comments, not the code.","why":"The JSDoc provides the types; the code is what gets checked against them."},{"text":"It type-checks the whole file, using the JSDoc comments as the types of <code dir=\"ltr\">ship</code> and its parameter.","why":"Correct. This lets you get real checking on risky JavaScript files before converting them."}],"answer":3}]},"final":[{"q":"<p>Which pair of changes makes both <code dir=\"ltr\">cancelOrder(customer.id)</code> and <code dir=\"ltr\">add(usdPrice, eurShipping)</code> compile errors?</p>","options":[{"text":"Brand <code dir=\"ltr\">OrderId</code> and <code dir=\"ltr\">CustomerId</code>, and type <code dir=\"ltr\">add</code> as <code dir=\"ltr\">add&lt;C&gt;(a: Money&lt;C&gt;, b: Money&lt;NoInfer&lt;C&gt;&gt;)</code>.","why":"Correct. Brands make same-shaped ids distinct, and <code dir=\"ltr\">NoInfer</code> stops the currency union from being inferred."},{"text":"Use literal unions for statuses and <code dir=\"ltr\">satisfies</code> on config objects.","why":"Both are good habits, but neither distinguishes two numeric ids or two currencies."},{"text":"Turn on <code dir=\"ltr\">exactOptionalPropertyTypes</code> and <code dir=\"ltr\">noUncheckedIndexedAccess</code>.","why":"These flags check optional properties and index access, not ids or currencies."},{"text":"Give <code dir=\"ltr\">add</code> and <code dir=\"ltr\">cancelOrder</code> <code dir=\"ltr\">const</code> type parameters.","why":"<code dir=\"ltr\">const</code> keeps literals in inference; it does not make ids or currencies incompatible."}],"answer":0},{"q":"<p>What is the type of <code dir=\"ltr\">summary</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"11\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> pick</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> extends</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> keyof</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">obj</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#953800;--shiki-dark:#FFA657\">keys</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> K</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[])</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Pick</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> { </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* … */</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> summary</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> pick</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(order, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'id'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'status'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">Partial&lt;Order&gt;</code>","why":"<code dir=\"ltr\">Pick</code> keeps the chosen properties required; nothing here makes them optional."},{"text":"<code dir=\"ltr\">Order</code>","why":"Only the keys you pass are kept, so the full <code dir=\"ltr\">Order</code> is not the result."},{"text":"<code dir=\"ltr\">Pick&lt;Order, keyof Order&gt;</code>","why":"<code dir=\"ltr\">K</code> is inferred from the arguments, not widened to every key."},{"text":"<code dir=\"ltr\">Pick&lt;Order, 'id' | 'status'&gt;</code>","why":"Correct. Each rest argument is an inference site for <code dir=\"ltr\">K</code>, and the literals are kept by the <code dir=\"ltr\">keyof T</code> constraint."}],"answer":3},{"q":"<p>A customer’s saved cart in <code dir=\"ltr\">localStorage</code> was written by last year’s version of the app, with a different shape. What is the right way to load it?</p>","options":[{"text":"<code dir=\"ltr\">JSON.parse(saved) as Cart</code>","why":"The cast trusts last year’s data blindly; the mismatch surfaces later as crashes."},{"text":"Use <code dir=\"ltr\">JSON.parse(saved)</code> directly, since it is typed <code dir=\"ltr\">any</code>.","why":"<code dir=\"ltr\">any</code> silently spreads the wrong shape through the app."},{"text":"Parse it as <code dir=\"ltr\">unknown</code> into a <code dir=\"ltr\">Result</code>, and fall back to an empty cart (or migrate it) when parsing fails.","why":"Correct. Old data is an expected case, so it becomes a handled failure at the boundary."},{"text":"Call an assertion function during render and let the error boundary show a crash screen.","why":"Stale storage is expected, not a bug, so crashing the page is the wrong response."}],"answer":2},{"q":"<p>What is <code dir=\"ltr\">NoNulls&lt;{ coupon: string | null; note?: string }&gt;</code>?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"ts\" data-index=\"12\"><div class=\"code-head\"><span class=\"code-title\">TypeScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">type</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> NoNulls</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { [</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> in</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> keyof</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> NonNullable</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#953800;--shiki-dark:#FFA657\">T</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#953800;--shiki-dark:#FFA657\">K</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]> };</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">{ coupon: string | null; note: string }</code>","why":"<code dir=\"ltr\">NonNullable</code> removes <code dir=\"ltr\">null</code> from <code dir=\"ltr\">coupon</code>, and the homomorphic mapping keeps <code dir=\"ltr\">note</code> optional."},{"text":"<code dir=\"ltr\">{ coupon: string; note?: string }</code>","why":"Correct. <code dir=\"ltr\">null</code> is removed from each property type, and the <code dir=\"ltr\">?</code> modifier is copied from the original."},{"text":"<code dir=\"ltr\">{ coupon: string; note: string }</code>","why":"The mapping is homomorphic, so it copies <code dir=\"ltr\">note</code>’s optional modifier; only <code dir=\"ltr\">-?</code> would remove it."},{"text":"<code dir=\"ltr\">never</code>","why":"Mapped types over an object type produce an object type, not <code dir=\"ltr\">never</code>."}],"answer":1},{"q":"<p>The payments team adds <code dir=\"ltr\">'requires-3ds'</code> to the <code dir=\"ltr\">PaymentError</code> union. <code dir=\"ltr\">errorMessage(e: PaymentError): string</code> switches on <code dir=\"ltr\">e.type</code> with no <code dir=\"ltr\">default</code>. What happens?</p>","options":[{"text":"<code dir=\"ltr\">errorMessage</code> fails to compile until a <code dir=\"ltr\">'requires-3ds'</code> case is added.","why":"Correct. With the new member unhandled, the end of the function is reachable, and the <code dir=\"ltr\">string</code> return type rejects that."},{"text":"It compiles and returns <code dir=\"ltr\">undefined</code> for the new error.","why":"The explicit <code dir=\"ltr\">: string</code> return type is exactly what prevents that from compiling."},{"text":"It compiles and throws at runtime for the new error.","why":"Nothing throws; the compiler stops the code before it can run."},{"text":"Nothing changes, because unions are checked only at runtime.","why":"Unions are compile-time types, and exhaustiveness is checked at compile time."}],"answer":0},{"q":"<p>Which string is assignable to <code dir=\"ltr\">type OrderPath = `/orders/${number}`</code>?</p>","options":[{"text":"<code dir=\"ltr\">'/orders/abc'</code>","why":"<code dir=\"ltr\">abc</code> is not a numeric string, so it does not match the <code dir=\"ltr\">${number}</code> placeholder."},{"text":"<code dir=\"ltr\">'/orders/'</code>","why":"An empty string is not a number, so the placeholder has nothing to match."},{"text":"<code dir=\"ltr\">'/orders/1042/lines'</code>","why":"The placeholder must match the rest of the string, and <code dir=\"ltr\">1042/lines</code> is not a number."},{"text":"<code dir=\"ltr\">'/orders/1042'</code>","why":"Correct. <code dir=\"ltr\">1042</code> is a numeric string, which is exactly what <code dir=\"ltr\">${number}</code> accepts."}],"answer":3},{"q":"<p>After turning on <code dir=\"ltr\">noUncheckedIndexedAccess</code>, which line becomes a compile error (with <code dir=\"ltr\">lines: Line[]</code>)?</p>","options":[{"text":"<code dir=\"ltr\">for (const line of lines) console.log(line.sku);</code>","why":"Iterating with <code dir=\"ltr\">for…of</code> yields actual elements, so the flag does not add <code dir=\"ltr\">undefined</code>."},{"text":"<code dir=\"ltr\">lines.map((line) =&gt; line.sku);</code>","why":"Array methods pass real elements to the callback, so they are unaffected."},{"text":"<code dir=\"ltr\">const [first] = lines; console.log(first.sku);</code>","why":"Correct. Destructuring by position is index access, so <code dir=\"ltr\">first</code> is <code dir=\"ltr\">Line | undefined</code> under the flag."},{"text":"<code dir=\"ltr\">console.log(lines.length);</code>","why":"<code dir=\"ltr\">length</code> is always a number; the flag only affects element and key lookups."}],"answer":2},{"q":"<p><code dir=\"ltr\">charge</code> is decorated with <code dir=\"ltr\">@retry(3)</code> on the line above <code dir=\"ltr\">@logged</code>. The gateway fails twice, then succeeds. How many log lines does <code dir=\"ltr\">logged</code> print for one call?</p>","options":[{"text":"1, because <code dir=\"ltr\">logged</code> wraps the whole retrying call","why":"That would be the order with <code dir=\"ltr\">@logged</code> written above <code dir=\"ltr\">@retry(3)</code>. Decorators apply from the bottom up."},{"text":"3, because <code dir=\"ltr\">logged</code> is applied first and <code dir=\"ltr\">retry</code> calls the logged method on every attempt","why":"Correct. The decorator nearest the method wraps it first, so each retry goes through the logging wrapper."},{"text":"0, because two decorators on one method cancel each other out","why":"Stacked decorators compose; they never cancel."},{"text":"6, because each decorator logs once per attempt","why":"Only <code dir=\"ltr\">logged</code> logs; <code dir=\"ltr\">retry</code> just calls the wrapped method again."}],"answer":1},{"q":"<p>Why can a <code dir=\"ltr\">DetailedOrder</code> (<code dir=\"ltr\">id</code>, <code dir=\"ltr\">status</code>, <code dir=\"ltr\">totalCents</code>, <code dir=\"ltr\">customer</code>) be passed where an <code dir=\"ltr\">Order</code> (<code dir=\"ltr\">id</code>, <code dir=\"ltr\">status</code>, <code dir=\"ltr\">totalCents</code>) is expected, but not the other way round?</p>","options":[{"text":"Every <code dir=\"ltr\">DetailedOrder</code> has all the properties <code dir=\"ltr\">Order</code> requires, so it belongs to the smaller set of values; an <code dir=\"ltr\">Order</code> may lack <code dir=\"ltr\">customer</code>.","why":"Correct. Assignability is the subset relation, and more required properties mean a smaller set."},{"text":"Because <code dir=\"ltr\">DetailedOrder</code> was declared with <code dir=\"ltr\">extends Order</code>.","why":"Declarations do not matter in a structural type system; only the shapes do."},{"text":"Because type names are compared alphabetically.","why":"TypeScript never compares names; it compares structure."},{"text":"Because <code dir=\"ltr\">Order</code> is an interface and interfaces only accept subtypes.","why":"Interfaces and type aliases follow the same structural rules here."}],"answer":0},{"q":"<p>Which signature is an unchecked cast in disguise?</p>","options":[{"text":"<code dir=\"ltr\">function sortByTotal&lt;T extends { totalCents: number }&gt;(orders: T[]): T[]</code>","why":"<code dir=\"ltr\">T</code> links input to output, so the result type is exactly what was passed in."},{"text":"<code dir=\"ltr\">function call&lt;R extends keyof Routes&gt;(route: R): Routes[R]['output']</code>","why":"<code dir=\"ltr\">R</code> is inferred from the route argument, so the result follows from what the caller wrote."},{"text":"<code dir=\"ltr\">function indexById&lt;T extends { id: number }&gt;(items: T[]): Map&lt;number, T&gt;</code>","why":"<code dir=\"ltr\">T</code> appears in the input and the output, linking them."},{"text":"<code dir=\"ltr\">function readSetting&lt;T&gt;(key: string): T</code>","why":"Correct. <code dir=\"ltr\">T</code> appears only in the return type, so the caller can pick any type and nothing checks it."}],"answer":3},{"q":"<p>What does <code dir=\"ltr\">declare module 'legacy-shipping-calc';</code> with no body do?</p>","options":[{"text":"It installs the matching <code dir=\"ltr\">@types</code> package.","why":"Declarations never install anything; they only describe code to the compiler."},{"text":"It generates types by reading the package’s JavaScript.","why":"TypeScript does not infer types for a package from a shorthand module declaration."},{"text":"It lets the import compile, typing everything imported from the package as <code dir=\"ltr\">any</code>.","why":"Correct. It is an escape hatch for a migration, not a substitute for real declarations."},{"text":"It causes a compile error until the body is filled in.","why":"The shorthand form is valid on its own; that is why it is easy to forget it is there."}],"answer":2},{"q":"<p>Which file should you convert to TypeScript first in a migration?</p>","options":[{"text":"<code dir=\"ltr\">checkoutPage.js</code>, the entry point that imports 30 other modules","why":"Converted first, it would import untyped code and end up full of <code dir=\"ltr\">any</code>."},{"text":"<code dir=\"ltr\">money.js</code>, imported by 40 files and importing nothing internal","why":"Correct. It is a leaf, so it can be fully typed today, and every file that imports it benefits immediately."},{"text":"The largest file in the repository, to get it out of the way","why":"Size says nothing about dependencies; a large file with untyped imports gains little."},{"text":"The most recently changed file","why":"Recency does not tell you whether its dependencies are typed yet."}],"answer":1}],"glossary":[{"id":"structural-typing","term":"Structural typing","definition":"TypeScript’s rule that a value is compatible with a type when it has the required shape, whatever the type is called. Two differently named types with the same properties are interchangeable.","lesson":"l-at-1-2"},{"id":"assignability","term":"Assignability","definition":"Whether a value of one type can be used where another type is expected. It works like the subset relation: a narrower set of values fits into a wider one.","lesson":"l-at-1-2"},{"id":"excess-property-check","term":"Excess property check","definition":"A check that flags unknown properties in a fresh object literal written directly where a type is expected. It catches typos, but values passed through a variable skip it.","lesson":"l-at-1-2"},{"id":"control-flow-analysis","term":"Control-flow analysis","definition":"How TypeScript tracks the type of a variable through branches, returns and assignments, so the same name can have a narrower type after a check than before it.","lesson":"l-at-1-3"},{"id":"narrowing","term":"Narrowing","definition":"Refining a wide type to a more specific one with a runtime check such as <code dir=\"ltr\">typeof</code>, <code dir=\"ltr\">===</code>, <code dir=\"ltr\">in</code>, <code dir=\"ltr\">instanceof</code> or a type predicate.","lesson":"l-at-1-3"},{"id":"discriminated-union","term":"Discriminated union","definition":"A union of object types that share a property with a different literal value in each member, such as <code dir=\"ltr\">status</code>. Checking that property narrows the whole object to one member.","lesson":"l-at-1-4"},{"id":"const-assertion","term":"as const","definition":"A const assertion that infers the narrowest type for a value: literals stay literal, arrays become readonly tuples and properties become readonly.","lesson":"l-at-1-5"},{"id":"satisfies","term":"satisfies","definition":"An operator that checks a value against a type without replacing the value’s inferred type, so you get validation and keep precise keys and literals.","lesson":"l-at-1-5"},{"id":"type-parameter","term":"Type parameter","definition":"A placeholder type in a generic function or type, such as <code dir=\"ltr\">T</code>, that links inputs to outputs. It should appear at least twice to add real type safety.","lesson":"l-at-2-1"},{"id":"generic-constraint","term":"Generic constraint","definition":"An <code dir=\"ltr\">extends</code> clause on a type parameter that limits which types it accepts, such as <code dir=\"ltr\">T extends { id: number }</code>, which also makes those properties usable inside the function.","lesson":"l-at-2-1"},{"id":"inference-site","term":"Inference site","definition":"A position in a parameter type where a type parameter appears. At a call, TypeScript collects a candidate from each site to decide what the type parameter is.","lesson":"l-at-2-2"},{"id":"const-type-parameter","term":"const type parameter","definition":"A type parameter declared with <code dir=\"ltr\">const</code> (TypeScript 5.0+), which infers arguments as if the caller had written <code dir=\"ltr\">as const</code>, keeping literals and readonly tuples.","lesson":"l-at-2-2"},{"id":"noinfer","term":"NoInfer","definition":"A built-in type (TypeScript 5.4+) that marks a position as check-only, so it is validated against a type parameter but never contributes an inference candidate.","lesson":"l-at-2-3"},{"id":"indexed-access-type","term":"Indexed access type","definition":"A type such as <code dir=\"ltr\">Order['status']</code> or <code dir=\"ltr\">T[number]</code> that looks up the type of a property, or of an array’s elements, using bracket syntax.","lesson":"l-at-3-1"},{"id":"mapped-type","term":"Mapped type","definition":"A type that loops over a union of keys and builds one property per key, as in <code dir=\"ltr\">{ [K in keyof T]?: T[K] }</code>, the definition of <code dir=\"ltr\">Partial</code>.","lesson":"l-at-3-2"},{"id":"key-remapping","term":"Key remapping","definition":"An <code dir=\"ltr\">as</code> clause in a mapped type that renames each key, often with a template literal. Mapping a key to <code dir=\"ltr\">never</code> removes it, which is how <code dir=\"ltr\">Omit</code> works.","lesson":"l-at-3-2"},{"id":"conditional-type","term":"Conditional type","definition":"A type of the form <code dir=\"ltr\">T extends U ? X : Y</code> that chooses between two types depending on whether <code dir=\"ltr\">T</code> is assignable to <code dir=\"ltr\">U</code>.","lesson":"l-at-3-3"},{"id":"distributive-conditional-type","term":"Distributive conditional type","definition":"A conditional type whose checked type is a naked type parameter. Given a union, it runs once per member and joins the results; wrapping both sides in brackets turns this off.","lesson":"l-at-3-3"},{"id":"infer","term":"infer","definition":"A keyword used inside the <code dir=\"ltr\">extends</code> clause of a conditional type to capture part of a matched type, as in <code dir=\"ltr\">ReturnType</code>, which captures a function’s return type.","lesson":"l-at-3-3"},{"id":"template-literal-type","term":"Template literal type","definition":"A string type built with backtick syntax from other types, such as <code dir=\"ltr\">`order.${OrderStatus}`</code>. Unions inside it expand into every combination.","lesson":"l-at-3-4"},{"id":"branded-type","term":"Branded type","definition":"A primitive intersected with a type-only property, such as <code dir=\"ltr\">number &amp; { readonly [brand]: 'OrderId' }</code>, so values with the same runtime type stop being interchangeable.","lesson":"l-at-4-1"},{"id":"smart-constructor","term":"Smart constructor","definition":"A function that validates a raw value and returns it as a branded type. It is the only place a cast to the brand should appear.","lesson":"l-at-4-1"},{"id":"exhaustiveness-check","term":"Exhaustiveness check","definition":"A compile-time guarantee that every member of a union is handled, usually by passing the leftover value to a parameter of type <code dir=\"ltr\">never</code> in a <code dir=\"ltr\">default</code> branch.","lesson":"l-at-4-1"},{"id":"result-type","term":"Result type","definition":"A discriminated union such as <code dir=\"ltr\">{ ok: true; value: T } | { ok: false; error: E }</code> that returns expected failures as values, so callers must handle them.","lesson":"l-at-4-2"},{"id":"type-predicate","term":"Type predicate","definition":"A function return type of the form <code dir=\"ltr\">value is T</code>. When the function returns true, the argument is narrowed to <code dir=\"ltr\">T</code> at the call site; the body itself is not verified.","lesson":"l-at-4-3"},{"id":"assertion-function","term":"Assertion function","definition":"A function whose return type is <code dir=\"ltr\">asserts value is T</code>. It throws when the check fails and narrows the value for the rest of the scope when it returns.","lesson":"l-at-4-3"},{"id":"using-declaration","term":"using declaration","definition":"A declaration that calls the value’s <code dir=\"ltr\">[Symbol.dispose]()</code> method when its block exits, by return or by throw, disposing several resources in reverse order.","lesson":"l-at-5-2"},{"id":"declaration-merging","term":"Declaration merging","definition":"The rule that several declarations with the same name, such as two interfaces, combine into one. It is how you extend lib types and library interfaces.","lesson":"l-at-5-3"},{"id":"module-augmentation","term":"Module augmentation","definition":"Adding to the types inside a module with <code dir=\"ltr\">declare module 'name' { … }</code> from a file that is itself a module, for example to extend a library’s interface.","lesson":"l-at-5-3"},{"id":"project-references","term":"Project references","definition":"A tsconfig feature that splits a codebase into separately built projects (<code dir=\"ltr\">composite: true</code>, built with <code dir=\"ltr\">tsc -b</code>), so unchanged parts are not re-checked.","lesson":"l-at-5-4"}]}