Skip to content

Instantly share code, notes, and snippets.

@crutchcorn
Last active November 29, 2021 19:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crutchcorn/54dba53ae282f3ac0c11cc40051b9c2a to your computer and use it in GitHub Desktop.
Save crutchcorn/54dba53ae282f3ac0c11cc40051b9c2a to your computer and use it in GitHub Desktop.
/**
* @callback objectMapCallback
* @param value - The value of the key that is currently being modified. Added as an attempt to duplicate Array.map `value`
* @param {string} key - The key that is currently being modified. Added as an attempt to duplicate Array.map `index`
* @param object - The original untouched object that the map function is being called on. Added as an attempt to duplicate Array.map `array`
*/
/**
* Map through all keys in an object and call a CB. Assign that CB's return value to the key in question
* @param object - The object to make this call on. This would otherwise be bound to `Object.prototype` but I don't like breaking the web
* @param {objectMapCallback} cb - The callback in order to run the `Object.map` function
* @returns - The object with it's keys altered by the cb param
*/
export function ObjectMap<T extends Record<string, any>>(object: T, cb: (value: T[string], key: keyof T, object?: T) => any): {
[key in keyof T]: any
} {
return Object.keys(object).reduce((prev, key) => {
prev[key] = cb(object[key], (key as any), object);
return prev;
}, ({} as any));
}
/**
* @callback objectFilterCallback
* @param value - The value of the key that is currently being checked against. Added as an attempt to duplicate Array.filter `value`
* @param {string} key - The key that is currently being used to check. Added as an attempt to duplicate Array.filter `index`
* @param object - The original untouched object that the filter function is being called on. Added as an attempt to duplicate Array.filter `array`
*/
/**
* Map through all keys in an object and call a CB. Decide to keep the Object key in the return object based on the truthyness of the CB's return value
* @param object - The object to make this call on
* @param {objectFilterCallback} cb - The callback in order to run the `Object.map` function
* @returns - The object with it's keys altered by the cb param
*/
export function ObjectFilter<T extends Record<string, any>>(object: T, cb: (value: T[string], key: keyof T, object?: T) => any): Partial<T> {
return Object.keys(object).reduce((prev, key) => {
const toKeep = cb(object[key], (key as any), object);
if (toKeep) {
prev[key] = object[key];
}
return prev;
}, ({} as any));
}
// NaN also, but `typeof NaN` === number
type Falsy = false | null | undefined | 0 | -0 | 0n | "";
/**
* Remove any keys where the value is falsy
*/
/**
* Remove any keys where the value is falsy
*/
export function RemoveFalsyObjectKeys<T extends Record<string, any>>(obj: T): {
[K in keyof T as Exclude<T[K], Falsy> extends never ? never : K]: Exclude<T[K], Falsy>;
} {
return Object.keys(obj).reduce((prev, key) => {
if (obj[key]) {
prev[key] = obj[key];
}
return prev;
}, {} as any);
}
/**
* Immutably set object property
*/
export function ObjectImmutablySetProp<T extends object, K extends keyof T, V>(object: T, key: K, val: V): {
[P in keyof T]: P extends K ? V : T[P];
} {
return Object.assign({}, object, {[key]: val}) as any;
}
/**
* Util type to only keep the keys from an array of an object
* @param obj - The object to make this call on
* @param keyArr - A string array of the keys to keep
* @constructor
*/
export function ObjectPick<Obj extends Record<string, any>, Keys extends Array<keyof Obj>>(obj: Obj, keyArr: Keys): {
[key in keyof Obj as Exclude<Keys[number], key>]: Obj[key];
} {
return Object.entries(obj).reduce((prev, [key, val]) => {
if (!keyArr.includes(key)) return prev;
// prev[key] = val;
return prev;
}, {} as any)
}
// --------------------------------------------------------------------------------------------------
type DeepReplaceKeysObj<Obj extends object, T> = {
[key in keyof Obj]:
Obj[key] extends Array<infer Q> ?
Array<DeepReplaceKeys<Q, T>> :
Obj[key] extends object ?
DeepReplaceKeys<Obj[key], T> :
T;
};
type DeepReplaceKeys<Obj, T> = Obj extends object ? DeepReplaceKeysObj<Obj, T> : Obj;
type B = DeepReplaceKeys<{test: {deep: false}}, true>;
// true
type A = B['test']['deep']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment