函数的打字稿联合/交集类型
Posted
技术标签:
【中文标题】函数的打字稿联合/交集类型【英文标题】:Typescript union/intersection types for functions 【发布时间】:2022-01-13 09:49:47 【问题描述】:当我有不同数量的参数和返回类型时,我试图了解如何指定类型(对于函数)。
这个函数可以:
接受 2 个参数(一个是可选的)并返回一个 Promise 接受 2 个参数(第二个是回调) 接受 3 个参数(第三个是回调)让我们首先为 3 种情况定义 3 种类型:
type Func1 = (a: string, b?: number) => Promise<void>;
type Func2 = (a: string, b: () => void) => void;
type Func3 = (a: string, c: number, b: () => void) => void;
现在我想定义一个包含这 3 个的类型。我读到您应该对函数类型使用交集。
type MultiFunction = Func1 & Func2 & Func3;
const f1: MultiFunction = async (a: string, b: number) => ;
const f2: MultiFunction = (a: string, b: () => void) => ;
const f3: MultiFunction = (a: string, c: number, b: () => void) => ;
f1("foo", 3);
f2("foo", () => );
f3("foo", 3, () => );
但这里的声明错误:
Type '(a: string, b: number) => Promise<void>' is not assignable to type 'MultiFunction'.
Type '(a: string, b: number) => Promise<void>' is not assignable to type 'Func2'.
Types of parameters 'b' and 'b' are incompatible.
Type '() => void' is not assignable to type 'number'.ts(2322)
const f1: MultiFunction
如果我使用联合:
type MultiFunction = Func1 | Func2 | Func3;
const f1: MultiFunction = async (a: string, b: number) => ;
const f2: MultiFunction = (a: string, b: () => void) => ;
const f3: MultiFunction = (a: string, c: number, b: () => void) => ;
f1("foo", 3);
f2("foo", () => );
f3("foo", 3, () => );
f1("foo", 3);
出现错误:
Expected 3 arguments, but got 2.ts(2554)
types_test.ts(3, 37): An argument for 'b' was not provided.
我的问题是,处理这个(和类似的)案例的正确方法是什么?
【问题讨论】:
【参考方案1】:像这样使用function overloading:
function func(a: string, b?: number):Promise<void>;
function func(a: string, b: () => void): void;
function func(a: string, c: number, b: () => void): void
function func(a: string, b?: any, c?: any): any
func("foo", 3);
// interpreted as
// function func(a: string, b?: number | undefined): Promise<void>
func("foo", () => );
// interpreted as
// function func(a: string, b: () => void): void
func("foo", 3, () => );
// interpreted as
// function func(a: string, c: number, b: () => void): void
TS Playground 链接:https://tsplay.dev/WoJnLm
【讨论】:
这很有趣,但是你会被func
作为函数名卡住。我的目的是提供一种类型,以便我可以创建任意数量的具有不同名称和不同实现的函数,但仍具有所提供的签名之一。您可能已经注意到,签名是针对经典的二分法“承诺或回调”函数样式的。
这是实现“承诺或回调”模式的一种方式。如果我没记错的话,这是我在 Mongoose 中看到的。如果您传递回调,则调用回调并返回 void,如果不是返回的承诺。但我猜重载不是你想要的。
是的,函数重载不是我打算用于我的用例的。我想定义一个涵盖这些功能的泛型类型(泛型在这里不是正确的术语,但无论如何)。我想这要么是不可能的,要么就是太乱了。以上是关于函数的打字稿联合/交集类型的主要内容,如果未能解决你的问题,请参考以下文章