簡體   English   中英

輸入接收動態參數的 function 的 returnType

[英]Type the returnType of a function that receive dynamic args

我有一個args接收可以輸入為string[string, Record<string, string>]的參數。

此 function 返回一個 object,其鍵是 function 的 args,如果這些 args 是類型string ,或者是第一個字符串,如果是數組中的第一個[string, Record<string, string>] 此 object 的所有值都輸入為string

例如:

exampleFunction("test1", "test2", ["test3", { result: "randomstring" }], "test4");

應該返回如下類型的內容:

type tResult = {
  test1: string;
  test2: string;
  test3: string;
  test4: string;
};

這個 function 可以采用任意數量的參數,並且這些參數中的任何一個都可以是string[string, Record<string, string>]

挑戰在於輸入這個exampleFunction的 returnType。

Typescript 沙箱鏈接在這里

我試着用tExampleFunctionReturn<T>輸入它:

type tExampleFunctionReturn<T extends tExampleFunctionArgs> = Record<
  T[number] extends string ? T[number] : T[number][0],
  string
>

但它不起作用。

有人可以幫幫我嗎? 謝謝您的回答。

TypeScript 編譯器無法推斷args.reduce(...)的 output 將是ExampleFunctionReturn<T>的值。 Array.prototype.reduce()的類型僅 model 累加器類型在操作期間保持不變的情況。 您正在逐步向 object 添加屬性,但編譯器僅將其視為類型{} ,它為您傳入的初始空 object 推斷出的類型。

試圖引導編譯器理解類型從{}到最終的 output 類型的逐漸突變可能是沒有希望的。 該語言可能需要microsoft/TypeScript#1213中要求的所謂的更高種類的類型才能表達這種關系,而且誰知道即使在那時推理也能起作用。 但如果沒有這種更高種類的類型,甚至沒有一個合理的起點。

如果您只是自己計算類型並斷言所討論的值屬於該類型,那么您將獲得更進一步的信息,而不是試圖讓編譯器推斷類型。 這是我的處理方法:

const exampleFunction = <K extends string>(
  ...args: Array<K | [K, Record<string, string>]>
) => {
  return args.reduce((acc, arg) => {
    if (typeof arg == "string") {
      return {
        ...acc,
        [arg]: "randomstring",
      };
    } else {
      return {
        ...acc,
        [arg[0]]: arg[1].result,
      };
    }
  }, {} as { [P in K]: string }); // assert here
};

請注意,我已經更改了您示例中的類型; 我不再使用與args rest 參數類型對應的泛型參數T 由於您要跟蹤的只是預期鍵的文字類型,因此我改為使用泛型類型參數K表示這些鍵的並集 那么args數組元素的類型是K | [K, Record<string, string>] K | [K, Record<string, string>]

這比從整個數組類型T開始並嘗試從中提取鍵更容易。

它還有一個優點是K extends string給編譯器一個你想要字符串文字類型的提示。 使用您的原始類型,除非您使用const斷言或類似的東西,否則值["test3", {...}]將不幸地擴大為string

無論如何,我已經斷言累加器的類型等同於Record<K, string> ,因此exampleFunction()的 output 是同一類型。 讓我們看看它是否有效:

const result = exampleFunction(
  "test1", "test2", ["test3", { result: "randomstring" }], "test4"
);
/* const result: {
    test1: string;
    test2: string;
    test3: string;
    test4: string;
} */

console.log(result.test1.toUpperCase()) // RANDOMSTRING

看起來不錯!

Playground 代碼鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM