繁体   English   中英

获取类型为“{ [key: string]: TYPE_X }”的对象并需要返回“TYPE_X[]”数组的函数的类型

[英]Type for a function that gets an object of type "{ [key: string]: TYPE_X }" and needs to return an array of "TYPE_X[]"

这是代码:

打字稿游乐场

interface TYPE_1 { foo1: "bar1" }
interface TYPE_2 { foo2: "bar2" }

interface OBJECT_1 {
    [key: string]: TYPE_1
}

interface OBJECT_2 {
    [key: string]: TYPE_2
}

type ARRAY_1 = TYPE_1[];
type ARRAY_2 = TYPE_2[];

type OBJ_IN = OBJECT_1 | OBJECT_2
type ARRAY_OUT = ARRAY_1 | ARRAY_2

function buildArrayFromObject(obj: OBJECT_1): ARRAY_1
function buildArrayFromObject(obj: OBJECT_2): ARRAY_2
function buildArrayFromObject(obj: OBJ_IN): ARRAY_OUT {
  const arr = [] as ARRAY_OUT;
  for (const item in obj) {
    arr.push(obj[item]);
  }
  return arr;
}

const obj1: OBJECT_1 = { id1: {foo1: "bar1" }, id2: {foo1: "bar1"}};
const obj2: OBJECT_2 = { id1: {foo2: "bar2" }, id2: {foo2: "bar2"}};

const array1 = buildArrayFromObject(obj1);
const array2 = buildArrayFromObject(obj2);

这是我得到的错误:

在此处输入图片说明

在此处输入图片说明

这段代码需要完成以下工作:

  • 取一个类型为{ [key: string]: TYPE_X }并返回一个TYPE_X[]数组

JS-wise 代码正在做它需要做的事情。 但是 Typescript 抱怨进入数组的类型。 我究竟做错了什么? 我该如何解决?

问题

在这种重载结构中,“输入”和“输出”之间没有关系。 您试图声明数组元素与预期的“out”类型与as ARRAY_OUT非常匹配,但您实际上并不知道预期的类型是什么。 回想一下, ARRAY_OUT只是ARRAY_OUT的别名ARRAY_1 | ARRAY_2 ARRAY_1 | ARRAY_2 所以当你写:

const arr = [] as ARRAY_OUT;

你说,这阵或者ARRAY_1ARRAY_2

您可以安全地push送到两个数组类型的联合的唯一方法是,您添加的值是否可以同时包含在两种数组类型中,即。 它必须是TYPE_1 & TYPE_2

但是您从对象中获得的值TYPE_1 | TYPE_2 TYPE_1 | TYPE_2 ,你不知道是哪个。 所以你得到错误“类型'TYPE_1 | TYPE_2'的参数不能分配给类型'TYPE_1 & TYPE_2'的参数”

解决方案

我们可以使用泛型,以便函数理解“输入”和“输出”值之间的配对。 不是将ARRAY_OUT定义为联合,而是将其定义为泛型,取决于输入对象的值。

我们知道返回的数组是一个数组,其元素是输入对象的值:

type Values<T> = T[keyof T];

type ARRAY_OUT<T> = Values<T>[];

所以函数变成:

function buildArrayFromObject<T extends OBJ_IN>(obj: T): ARRAY_OUT<T> {
  const arr = [] as ARRAY_OUT<T>;
  for (const item in obj) {
    arr.push(obj[item]);
  }
  return arr;
}

(注意: ARRAY_OUT<T>(T[keyof T])[] ,您可以使用任一作为返回类型)

这有效而重载无效的原因是因为“输入”和“输出”的T相同。

打字稿游乐场链接

在@Linda 的回答的帮助下,这就是我想出的:

type GENERIC_OBJECT<T> = {
  [key: string] : T
}

export function buildArray<T>(obj: GENERIC_OBJECT<T>) : T[] {
  const arr = [];
  for (const item in obj) {
    arr.push(obj[item]);
  }
  return arr;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM