Created
March 19, 2026 06:55
-
-
Save 5cover/3b6ad211d2024ffbf8488b4f4a1e0914 to your computer and use it in GitHub Desktop.
Branded exact object type TypeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface Config { | |
| port: number | |
| log_file: string; | |
| log_level: 'error' | 'warning' | 'info' | |
| } | |
| const config = exact<Config>(['port','log_file','log_level']); | |
| const src = {port: 1000, log_file: 'stdout', log_level: 'info', junk: 'more'} as Config | |
| const x = config(src); | |
| const e = entries(x); | |
| console.log(x, e) | |
| function exact<T extends object>(keys: UnionToTuple<keyof T> & readonly (keyof T)[]) { | |
| return (obj: Readonly<T>) => Object.fromEntries(keys.map(k => [k, obj[k]] as const)) as Exact<T> | |
| } | |
| function entries<T extends object>(obj: Exact<T>) { | |
| return Object.entries(obj as T) as { [K in keyof T]: [K, T[K]]}[keyof T] | |
| } | |
| type UnionToTuple<T> = UnionToIntersection< | |
| T extends never ? never : (t: T) => T | |
| > extends (_: never) => infer W | |
| ? [...UnionToTuple<Exclude<T, W>>, W] | |
| : []; | |
| type UnionToIntersection<U> = ( | |
| U extends never ? never : (arg: U) => never | |
| ) extends (arg: infer I) => void | |
| ? I | |
| : never; | |
| type Exact<T extends object> = Brand & T | |
| type Brand = { readonly __brand?: unique symbol } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment