[英]Why is the ReturnType of 'value is Type' function boolean?
[英]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。
我試着用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
看起來不錯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.