TypeScript Advanced — Series 2

Preview — 3 of 10 questions

javascript
type NonFunctionKeys<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];
interface Config { host: string; port: number; connect(): void; }
type DataKeys = NonFunctionKeys<Config>;
ADataKeys is keyof Config, unchanged
BDataKeys is "connect" only
CDataKeys is "host" | "port" — the mapped type replaces every function-valued property's key with never, and indexing the resulting object type with [keyof T] collects a union of only the keys that survived (weren't mapped to never)
DCompile-time error — a mapped type can't conditionally resolve to never

javascript
interface Person { name: string; age: number; }
type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] };
type PersonGetters = Getters<Person>;
declare const g: PersonGetters;
g.getName();
g.name;
Ag.getName() compiles fine, returning string; g.name is a compile-time error — key remapping via as fully replaces the original keys with the newly generated getter-method names, so the original property names no longer exist on PersonGetters
BPersonGetters ends up with both the original keys (name, age) and the renamed getter keys (getName, getAge)
CCompile-time error — Capitalize can't be used inside a key-remapping template literal
DBoth g.getName and g.name are valid, equivalent ways to access the same underlying value

javascript
type Last<T extends unknown[]> = T extends [...infer _, infer L] ? L : never;
type A = Last<[1, 2, 3]>;
type B = Last<[]>;
AA is 3, and B is never — the rest pattern ...infer _ consumes every element except the final one, letting infer L capture just the last; an empty tuple has no last element, so the conditional's shape doesn't match and it falls to never
BA is the whole tuple [1, 2, 3], and B is never
CA is 3, and B is undefined
DCompile-time error — infer can only appear once per conditional type

Sign up free to play

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