Challenge 2: Exploit Distribution — Possible Solution ==================================================================== // Step 1: for each key K, produce K itself if the value is NOT a function, // or `never` if it IS a function. This is the distributive part — it runs // once per key via the mapped type, not once per union member, but the // underlying trick (things that fail the check become `never` and vanish // from a union) is exactly the same principle Exclude uses. type NonFunctionKeys = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]; // --- Usage --- interface Example { id: string; name: string; age: number; greet: () => void; save: (data: unknown) => Promise; } type Keys = NonFunctionKeys; // Keys = "id" | "name" | "age" // "greet" and "save" mapped to `never`, and `never` disappears when the // mapped type is indexed by `[keyof T]` to collapse it into a union. // A practical use: build a type containing only the non-function properties. type NonFunctionProps = Pick>; type ExampleData = NonFunctionProps; // ExampleData = { id: string; name: string; age: number } // greet and save are excluded entirely — useful for stripping methods // off a class instance type before, say, serializing it to JSON. WHY THIS WORKS -------------- - The mapped type `{ [K in keyof T]: ... }` produces an intermediate object type where each key maps to either itself (K) or `never`, depending on whether that property's value type extends Function. - Indexing that intermediate type with `[keyof T]` produces a union of all the mapped values — and since TypeScript automatically removes `never` from a union, only the keys that survived the check (the non-function ones) remain. - Combining NonFunctionKeys with the built-in Pick utility type turns "a union of allowed keys" into "an actual object type containing only those keys" — a common two-step pattern (compute keys, then Pick) for filtering object shapes.