我有一些包含DB文档的对象,我经常需要将它们转换为数组。
示例:
const MY_OBJECT = {
docId_1: {...doc1},
docId_2: {...doc2},
docId_3: {...doc3},
// AND SO ON
}
我需要将其转换为这样的数组:
const MY_ARRAY_FROM_OBJECT = [
{...doc1},
{...doc2},
{...doc3},
// AND SO ON...
]
这是我用来进行转换的代码:
function buildArrayFromObject(obj) {
const keys = Object.keys(obj);
const arr = [];
for (const key of keys) {
arr.push(obj[key]);
}
return arr;
}
我需要键入该函数,以便可以将其用于具有以下类型的对象:
interface BLOGPOSTS_ALL {
[key: string]: BLOGPOST
}
interface PRODUCTS_ALL {
[key: string]: PRODUCT
}
因此,当我使用每个不同的对象调用它们时,我希望Typescript知道返回数组的类型。
例如:
const BLOGPOSTS_ALL_ARRAY = buildArrayFromObject(BLOGPOSTS_ALL); // SHOULD BE "BLOGPOST[]"
const PRODUCTS_ALL_ARRAY = buildArrayFromObject(PRODUCTS_ALL); // SHOULD BE "PRODUCT[]"
这是我尝试过的:
function buildArrayFromObject<T, K extends keyof T>(obj: T): T[K][] {
const keys = Object.keys(obj);
const arr = [];
for (const key of keys) {
arr.push(obj[key]);
}
return arr;
}
但是我遇到了这个错误:
TypeScript正在将函数的返回类型评估为类型never[]
答案 0 :(得分:1)
您可以执行以下操作:
创建抽象类型以定义数据库处理的外观:
// Create an Entity type to define how your database objects look like
type Entities<T> = { [key: string]: T | undefined }
因此,您可以这样表达您的产品和博客文章:
type BLOGPOSTS = Entities<BLOGPOST>;
type PRODUCTS = Entities<PRODUCT>;
为了将它们以类型安全的方式转换为数组,可以使用JavaScript API提供的Object.values
方法-有关更多信息,请参见MDN
可以用以下方法替换方法buildArrayFromObject
:
const isNil = <T>(a: T | null | undefined): a is null | undefined => a === null || a === undefined;
const isAssigned = <T>(a: T | null | undefined): a is T => !isNil(a);
const entitiesToArray = <T>(entity: Entities<T>): T[] => Object.values(entity).filter(isAssigned);
此方法使用Object.values
方法将对象转换为数组。之后,将其过滤以包含没有未定义值的数组。因此,我使用了两个辅助方法isAssigned
和isNil
。请参见此CodeSandbox的示例:Code SandBox
基于您的担心,IE11不支持Object.value方法,您可以为该方法添加一个polyfill。通过将polyfill粘贴或使用npm将其添加到您的项目中。 或者,您可以通过以下答案Use Object.keys to mimick Object.values
替换此代码