Skip to content

Instantly share code, notes, and snippets.

@5cover
Created March 19, 2026 06:55
Show Gist options
  • Select an option

  • Save 5cover/3b6ad211d2024ffbf8488b4f4a1e0914 to your computer and use it in GitHub Desktop.

Select an option

Save 5cover/3b6ad211d2024ffbf8488b4f4a1e0914 to your computer and use it in GitHub Desktop.
Branded exact object type TypeScript
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