我有一个Object.entries
类型,如下所示:
type _ObjectEntries<T extends Record<string, any>> = {
[K in keyof T]: [K, T[K]];
}[keyof T][];
function objectEntries<T extends Record<string, any>>(
obj: T,
): _ObjectEntries<{
[K in keyof T]-?: T[K]
}> {
return Object.entries(obj);
}
当我知道物体的确切形状时,这很有效,例如:
const obj1: { a: number, b?: number } = { a: 1, b: 2 };
const entry1 = objectEntries(obj1)[0]; // ["a", number] | ["b", number]
尽管b
是可选的,但它仍然有效。
但是,如果我不知道对象的确切形状(即它具有任意关键点),这会将undefined
添加到值中:
const obj2: Partial<Record<string, number>> = { a: 1, b: 2 };
const entry2 = objectEntries(obj2)[0]; // [string, number | undefined]
我希望类型是[string, number]
。
我认为问题出在Partial<Record<string, number>>
。我认为这意味着“只要键存在,值就必须是一个数字”。然而,TS似乎将其解释为“对于任何键,值必须是数字或未定义的”。
我知道区分optional keys和undefined
有很多问题。但是,特别是对于Object.entries
,有没有可行的变通方法?我考虑标记对象,以了解它们是否可以具有undefined
值,但这似乎太老生常谈了。
发布于 2021-07-16 14:19:48
也许您可以使用NonNullable<T>
,它排除了undefined
和null
,或者如果您只想排除undefined
,也可以使用Exclude<T, undefined>
。
function objectEntries<T extends Record<string, any>>(
obj: T,
): _ObjectEntries<{
[K in keyof T]-?: NonNullable<T[K]>
}> {
return Object.entries(obj);
}
https://stackoverflow.com/questions/68404128
复制相似问题