Deep Readonly Configuration Type
Make a nested configuration object deeply readonly so accidental mutation of shared settings fails at compile time rather than at runtime.
Code
export type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends (infer U)[]
? readonly DeepReadonly<U>[]
: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};
export interface ServerConfig {
port: number;
db: { host: string; pool: { min: number; max: number } };
features: string[];
}
export function freeze<T>(value: T): DeepReadonly<T> {
const deepFreeze = (node: unknown): void => {
if (node && typeof node === "object") {
Object.values(node as Record<string, unknown>).forEach(deepFreeze);
Object.freeze(node);
}
};
deepFreeze(value);
return value as DeepReadonly<T>;
}Report a problem with this exampleOpens a pre-filled issue on GitHub.