这是我到目前为止所尝试的:
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 };
}, {});
};
TS操场。
const dirtyObject = {
a: 1,
b: null,
c: undefined,
};
console.log(purifyObject(dirtyObject)); // { a: 1 }
我试图得到一个对象,它可以有值空,或未定义,并返回同一对象的类型,不包括键值对值空,和未定义。怎么写呢?
紧跟上面的例子:
{
a: number,
b: null,
c: undefined,
}
应该返回
{ a: number }
{ [key: string]?: string | undefined | null }
应该返回
{ [key: string]?: string }
或
{ [key: string]: string }
您可以使用带有as
子句的映射类型来排除包含null
或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>);
};
操场上联系
Typescript playground link
首先你需要建立一个包含脏值的键的联合,像这样:
/**
* 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];
然后你可以排除这些键,并使用映射类型来构建一个新的类型,如下所示:
/**
* 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]
}