首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TypeScript:从对象数组创建新的对象类型

TypeScript:从对象数组创建新的对象类型
EN

Stack Overflow用户
提问于 2022-08-30 21:44:21
回答 1查看 97关注 0票数 1

是否有方法从对象数组中推断名称值,并让新对象使用这些值作为输出类型的键?

代码语言:javascript
复制
interface TypeA {
  name: string;
  value: number;
}

interface TypeB {
  [key: string]: { value: any };
}

// can this be created without hard-coding a new type containing the values?
interface OutputType {
  test: {value: any},
  test2: {value: any},
}

const arrayOfObjectsToObject = (array: TypeA[]):OutputType =>
  array.reduce((acc: TypeB, { name, value }: TypeA) => {
    acc[name] = { value };
    return acc;
  }, {});

const result = arrayOfObjectsToObject([ // {test:{value:1}, test2:{value:2}} etc...
  { name: 'test', value: 1 },
  { name: 'test2', value: 2 }
]);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-30 22:11:06

我们可以定义一个泛型类型ToOutputType,它接受一个元组,并使用映射类型将该类型转换为所需的对象类型。

代码语言:javascript
复制
type ToOutputType<T extends { name: string, value: any }[]> = {
    [K in T[number] as K["name"]]: { value: K["value"] }
} 

我们还修改了arrayOfObjectsToObject,使其成为通用的。

代码语言:javascript
复制
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

const arrayOfObjectsToObject = 
  <
    T extends { name: K, value: any }[], 
    K extends string
  >(array: readonly [...T]): Expand<ToOutputType<T>> => {
    return array.reduce((acc, { name, value }) => {
      acc[name] = { value };
      return acc;
    }, {} as any) as Expand<ToOutputType<T>>;
  }

T将保存传递给函数的元组。K将用于将元组中的字符串缩小到文字类型。我们使用类型Expand<ToOutputType<T>>作为返回类型。使用Expand类型只是为了使类型更漂亮。

调用该函数时,将得到以下结果。

代码语言:javascript
复制
const result = arrayOfObjectsToObject([
  { name: 'test', value: 1 },
  { name: 'test2', value: 2 }
]);

const a = result.test
//    ^? { value: number; }

const b = result.test2
//    ^? { value: number; }

注意,在这两种情况下,value的类型都是number。TypeScript自动将数字扩展到number。为了防止这种情况,我们可以使用as const

代码语言:javascript
复制
const result = arrayOfObjectsToObject([
  { name: 'test', value: 1 },
  { name: 'test2', value: 2 }
] as const);

const a = result.test
//    ^? { value: 1; }

const b = result.test2
//    ^? { value: 2; }

游乐场

如果您不想使用as const,我们也可以使用一种特殊的通用类型进行推理。

代码语言:javascript
复制
type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};

const arrayOfObjectsToObject = 
  <
    T extends { name: K, value: N }[], 
    N extends { [k: string]: N | T | [] } | Narrowable,
    K extends string
  >(array: readonly [...T]): Expand<ToOutputType<T>> => {
    return array.reduce((acc, { name, value }) => {
      acc[name] = { value };
      return acc;
    }, {} as any) as Expand<ToOutputType<T>>;
  }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73548743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档