Skip to content

Instantly share code, notes, and snippets.

@mrclay
Last active July 12, 2023 20:11
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 mrclay/a797ad7e4989e416412b3aaafddbbc2f to your computer and use it in GitHub Desktop.
Save mrclay/a797ad7e4989e416412b3aaafddbbc2f to your computer and use it in GitHub Desktop.
Destructure objects so that defaults can be given for nulls, too.
type OmitNull<T> = T extends null ? Exclude<T, null> | undefined : T;
type OmitNullProps<T extends object> = { [Key in keyof T]: OmitNull<T[Key]> };
/**
* Allow destructuring an object, turning any null properties into undefined so
* a default can be given. If the given object may be null/undefined, then every
* property may be undefined.
*
* Useful for assigning defaults for properties that may be null. In a usual destructuring
* assignment, nulls are passed through so you can't provide a default for that case:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#default_value
*/
export function withoutNulls<T extends object>(value: T): OmitNullProps<T>;
export function withoutNulls<T extends object>(
value: T | null | undefined,
): Partial<OmitNullProps<T>>;
export function withoutNulls(value: unknown) {
return Object.fromEntries(
Object.entries(value || {}).filter(kv => kv[1] !== null),
);
}
// DEMO
const foo = {
string1: 'String',
string2: 'String',
maybeNull1: 'maybeNull' as string | null,
maybeNull2: 'maybeNull' as string | null,
};
// ✓ Possibilities of null are replaced by undefined.
const {
string1,
maybeNull1,
} = withoutNulls(foo);
// ✓ If the given object may be null/undefined then everything might be undefined.
const {
string2,
maybeNull2,
// ✓ Unrecogniged keys flagged as errors.
unrecognized,
} = withoutNulls(null as typeof foo | null);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment