Skip to content

Instantly share code, notes, and snippets.

@nathansmith
Last active April 15, 2024 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathansmith/a6c67e9e7095e33dc16a1f0a4c4cfd6a to your computer and use it in GitHub Desktop.
Save nathansmith/a6c67e9e7095e33dc16a1f0a4c4cfd6a to your computer and use it in GitHub Desktop.
Type safe, recursive `Object.freeze`.
// ======
// Types.
// ======
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends Record<PropertyKey, unknown> ? DeepReadonly<T[K]> : T[K];
};
// ===========================
// Helper: deep freeze object.
// ===========================
/**
* This function accepts an array or object. It freezes
* the incoming value and any descendants recursively.
*
* @template T
* @param {T} obj
* @returns {Readonly<T>}
*/
const deepFreeze = <T>(obj: T): DeepReadonly<T> => {
// Valid object: YES.
if (obj && ['function', 'object'].includes(typeof obj)) {
// Loop through.
Reflect.ownKeys(obj as object).forEach((key): void => {
// Recursion.
deepFreeze(obj[key as keyof T]);
});
}
// Expose object.
return Object.freeze(obj);
};
// Export.
export { deepFreeze };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment