Advanced Generics — Series 3

Preview — 3 of 10 questions

javascript
type OptionalKeys<T> = {
  [K in keyof T]-?: {} extends Pick<T, K> ? K : never
}[keyof T];

type R = OptionalKeys<{ a: string; b?: number; c?: boolean }>;
A"b" | "c"
B"a" | "b" | "c" — every key survives, because {} extends any object type
Cnever — the -? modifier makes all keys required before the check runs
DCompile-time error — Pick cannot take a single key from a mapped type's K

javascript
type Tail<T extends readonly unknown[]> =
  T extends readonly [unknown, ...infer R] ? R : never;

type A = Tail<[1, 2, 3]>;
type B = Tail<[]>;
type C = Tail<string[]>;
AA is [2, 3], B is [], C is string[]
BA is [1, 2], B is never, C is never
CA is [2, 3], B is never, C is never
DCompile-time error — infer may not be combined with a rest element

javascript
type Action =
  | { type: "add"; n: number }
  | { type: "del"; id: string };

type Add = Extract<Action, { type: "add" }>;
type Payload = Omit<Add, "type">;
AAdd is Action — Extract keeps every member whose keys overlap
BAdd is { type: "add"; n: number } and Payload is { n: number }
CAdd is { type: "add" } — only the properties named in the pattern survive
DAdd is never — an object literal type can never extend another object literal type

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.