簡體   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