This is what I've tried so far:
export const purifyObject = <
T extends Record<string, unknown>,
K extends keyof T,
V extends K = T[K] extends null | undefined ? never : K,
P = { [VK in keyof V]: T[VK] },
>(
object: T,
): P => {
const keys = Object.keys(object) as (keyof T)[];
return keys.reduce((pureObject, key) => {
const value = object[key];
if ([null, undefined].includes(value)) return pureObject;
return { ...pureObject, [key]: value };
}, {});
};
const dirtyObject = {
a: 1,
b: null,
c: undefined,
};
console.log(purifyObject(dirtyObject)); // { a: 1 }
I'm trying to get an object which can have values null, or undefined, and returns the type of the same object excluding the key-value pairs with values null, and undefined. How to write the type for that?
Following the above example:
{
a: number,
b: null,
c: undefined,
}
Should return
{ a: number }
{ [key: string]?: string | undefined | null }
Should return
{ [key: string]?: string }
or
{ [key: string]: string }
CodePudding user response:
You can use a mapped type with an as
clause to exclude keys that contain null
or undefined
type PurifyObject<T> ={ [P in keyof T as T[P] extends null | undefined ? never : P]: T[P] }
export const purifyObject = <
T extends Record<string, unknown>
>(
object: T,
): PurifyObject<T> => {
const keys = Object.keys(object) as (keyof T)[];
return keys.reduce((pureObject, key) => {
const value = object[key] as never;
if ([null, undefined].includes(value)) return pureObject;
return { ...pureObject, [key]: value };
}, {} as PurifyObject<T>);
};
CodePudding user response:
First you need build an union of keys which contains dirty value like so:
/**
* Build an union of keys which contains dirty value
*/
type DirtyKeys <Object extends Record<string,unknown>> = {
[key in keyof Object]: Object[key] extends null | undefined ? key : never;
}[keyof Object];
Then you can exclude these keys and use mapped types to build a new type like so:
/**
* Map the type to new type excluding dirty keys from `keyof Object` which does not contain null or undefined as value
* Nested Objects are supported too
*/
type Purify<Object extends Record<string,unknown>> = {
[key in Exclude<keyof Object, DirtyKeys<Object>>]: Object[key] extends Record<string,unknown>
? Purify<Object[key]>
: Object[key]
}