typescript - 输入接收动态参数的函数的 returnType
问题描述
我有一个接收函数,args
可以键入 asstring
或 as [string, Record<string, string>]
。
此函数返回一个对象,如果这些 args 被键入,则该对象的键是函数的 args,string
如果这些 arg 被键入,则返回数组中的第一个字符串[string, Record<string, string>]
。该对象的所有值都输入为string
例如 :
exampleFunction("test1", "test2", ["test3", { result: "randomstring" }], "test4");
应该返回如下类型的内容:
type tResult = {
test1: string;
test2: string;
test3: string;
test4: string;
};
此函数可以采用任意数量的 args,并且这些 args 中的任何一个都可以是string
或[string, Record<string, string>]
。
挑战在于输入 this 的 returnType exampleFunction
。
我试着用以下方式输入tExampleFunctionReturn<T>
:
type tExampleFunctionReturn<T extends tExampleFunctionArgs> = Record<
T[number] extends string ? T[number] : T[number][0],
string
>
但它不起作用。
有人可以帮帮我吗 ?谢谢您的回答。
解决方案
TypeScript 编译器无法推断 的输出args.reduce(...)
将是ExampleFunctionReturn<T>
. 仅用于Array.prototype.reduce()
模拟累加器类型在操作期间保持不变的情况。您正在逐步向对象添加属性,但编译器仅将其视为 type {}
,它为您传入的初始空对象推断出的类型。
试图引导编译器理解从类型{}
到最终输出类型的逐渐变异可能是没有希望的。该语言可能需要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
};
请注意,我已经更改了您示例中的类型;我不再使用T
对应于args
其余参数类型的泛型参数。由于您要跟踪的只是预期键的文字类型,因此我改为使用泛型类型参数K
表示这些键的联合。那么args
数组元素的类型是K | [K, Record<string, string>]
。
这比从整个数组类型开始T
并尝试从中提取键更容易。
它还具有K extends string
向编译器提示您需要字符串文字类型的优点。不幸的是,使用您的原始类型,除非您使用断言或类似的东西,否则该值["test3", {...}]
将被扩大。string
const
无论如何,我已经断言累加器的类型等同于Record<K, string>
,因此 的输出exampleFunction()
是相同的类型。让我们看看它是否有效:
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
看起来不错!
推荐阅读
- php - 按第一个元素组合和求和数组元素
- java - 传递到持久的分离实体:JPA OneToMany 关系
- visual-studio-code - 我想要一些关于如何在 Visual Studio Code 中使用 Mark down 功能的帮助?
- ios - Swift:UITableViewCell 中的像素化文本
- javascript - 运行 yarn dev 后出现 Fusion.js 错误
- python - Decoding email text with bytes.decode(encoding)
- python - Efficiently assign columns headers to csv file
- c# - 快速选择创建分区问题
- javascript - Primefaces RadioButton,JS功能不起作用
- xcode - UIView 中的 UIButton 想要在 ViewController 的 func 中调用 isHidden