typescript - 打字稿:当函数可以是多种函数类型时,函数参数出错
问题描述
我有以下示例代码:
type GetMultipleFunction1 = () => Promise<string[]>;
type GetMultipleFunction2 = (data: number) => Promise<string[]>;
type GetMultipleFunction = GetMultipleFunction1 | GetMultipleFunction2;
function test(func: GetMultipleFunction): Promise<string[]> {
return func();
}
function getStrings(data: number): Promise<string[]> {
return new Promise(function (resolve, reject) {
resolve(['hello', 'hi']);
}) }
test(getStrings);
为什么我会收到错误消息(第 6 行return func()
):
预期 1 个参数,但得到 0。
我觉得 GetMultipleFunction 可以是类型 1 或类型 2。类型 1 不需要参数。
我需要如何更改代码以消除警告?
--
编辑:我想要实现的目标:
我基本上想要一个接受函数作为参数的函数。在我的例子test
中。它应该接受一个带参数的函数和一个不带参数的函数。这甚至可能吗?
代码示例:
type GetMultipleFunction1 = () => string[];
type GetMultipleFunction2 = (data: number) => string[];
export type GetMultipleFunction = GetMultipleFunction1 | GetMultipleFunction2;
function test(func: GetMultipleFunction, data?: number): string[] {
if (data) return func(data);
return func() // here should be no warning
}
function getStrings1(data: number): string[] {
return [`hello-${data}`, 'hi'];
}
function getStrings2(): string[] {
return ['hello', 'hi']
}
test(getStrings1, 2);
test(getStrings2);
--
我想要实现的更具体的解释:我正在使用 Vue3 组合函数来提取 Get 请求。通常我可以只调用: /api/groups/
,但有时我需要将参数传递给我的 get 请求函数:/api/groups/3/members/
现在需要将数字 3 作为参数传递。
解决方案
问题出在这一行type GetMultipleFunction = GetMultipleFunction1 | GetMultipleFunction2;
。
两个函数的联合永远不会以您期望的方式运行。它产生一个函数,其中参数是两个函数参数的相交类型。看小例子:
type Foo = (arg: { age: number }) => void
type Bar = (arg: { name: string }) => void
type Union = Foo | Bar
declare let func:Union
// let func: (arg: { age: number;} & { name: string;}) => void
func()
这是设计使然,这是调用函数联合的最安全方式。
在您的示例中:
function test(func: GetMultipleFunction): Promise<string[]> {
return func(); // < ------ ERROR
}
最安全的调用方式func
是提供参数。它将涵盖两种情况。如果您传递了一个不需要参数的函数 - 它不会造成任何伤害。
我认为在这个例子中它使用函数交集而不是联合。像这儿:
type GetMultipleFunction1 = () => Promise<string[]>;
type GetMultipleFunction2 = (data: number) => Promise<string[]>;
export type GetMultipleFunction = GetMultipleFunction1 & GetMultipleFunction2;
function test(func: GetMultipleFunction): Promise<string[]> {
return func(); // no error
}
function getStrings(data: number): Promise<string[]> {
return new Promise(function (resolve, reject) {
resolve(['hello', 'hi']);
})
}
test(getStrings); // error
但是,我们在一个新的地方遇到了错误:test(getStrings); // error
.
这是因为Type '(data: number) => Promise<string[]>' is not assignable to type '() => Promise<string[]>'.
我很难猜出你想在这里实现什么。data
参数 ingetStrings
未使用。
你也可以重载你的test
函数:
type GetMultipleFunction1 = () => Promise<string[]>;
type GetMultipleFunction2 = (data: number) => Promise<string[]>;
function test(func: GetMultipleFunction2): Promise<string[]>
function test(func: GetMultipleFunction1): Promise<string[]>
function test(func: (...args: any[]) => Promise<string[]>): Promise<string[]> {
return func(); // ok
}
function getStrings(data: number): Promise<string[]> {
return new Promise(function (resolve, reject) {
resolve(['hello', 'hi']);
})
}
test(getStrings); // ok
test(() => Promise.resolve(42)); // expected error
不用担心我已经使用了(...args: any[])
,测试功能仍然只接受 GetMultipleFunction1
要么GetMultipleFunction2
更新
您可以完全摆脱联合函数和重载。只需使用休息参数
function test<Fn extends (...args: any[]) => string[]>(func: Fn, ...params: Parameters<Fn>): string[] {
return func(...params) // ok
}
function getStrings1<Data extends number>(data: Data) {
return [`hello-${data}`, 'hi'];
}
function getStrings2() {
return ['hello', 'hi']
}
test(getStrings1, 2);
test(getStrings1); // expected error
test(getStrings2);
推荐阅读
- docker - Docker push:使用多个标签推送一次图像
- node.js - 带有graphql和sqs的lambda在nodejs中向sqs发送2条消息?
- azure - 在 Azure 设备预配服务中为多个设备使用相同的 X509 证书
- python - Odoo,如何从 many2one 字段中隐藏项目?
- mysql - 如何使用 MariaDB 10.0.37 在 Slackware 14.2 上进行热备份(在线备份)?
- vb.net - 获取文件首扇区地址
- swift - Swift 使用子字典设置 firebase 字典的值
- scala - 在scala中发送带有多个附件的电子邮件
- sparql - 删除三重 Apache Jena
- windows-10 - LLVM 7.0.1 安装程序中的文本损坏