英文:
Make similar function but exclude the last argument
问题
我尝试创建一个类型 B,其定义与类型 A 相同,但省略了最后一个参数。我尝试了以下方法,但它仍然要求传入 2 个参数。
type Callback = (msg: string) => void;
type A = (A: string, B: Callback) => void;
type B = <U extends Exclude<Parameters<A>, Callback>>(...args: U) => void;
const b: B = (...args) => {};
b("some string"); // 预期 2 个参数,但只传入了 1 个。
我该如何正确实现这个目标?
英文:
I'm trying to create a type B which defines same function as type A but omits the last parameter. I've tried the following but it still asks for 2 parameters.
type Callback = (msg: string) => void;
type A = (A: string, B: Callback) => void;
type B = <U extends Exclude<Parameters<A>, Callback>>(...args: U) => void;
const b: B = (...args) => {};
b("some string"); // Expected 2 arguments, but got 1.
How can I do this properly?
答案1
得分: 1
以下是翻译好的内容:
您可以使用条件类型推断来排除函数类型的最后一个参数:
type ExcludeLastParam<T extends (...args: any) => any> =
T extends (...args: [...infer I, any]) => infer R ? (...args: I) => R : never;
这将匹配T
与(...args: [...I, any]) => R
,其中I
和R
是编译器使用infer
关键字进行推断的一些部分。请注意,[...I, any]
是可变元组类型,通过将[...I, any]
与元组类型(比如 [a: string, b: Callback]
)进行匹配,编译器将推断I
为元组的“初始”部分,不包括最后一个条目(因为任意类型会匹配任何类型)(比如 [a: string]
)。
让我们来测试一下:
type Callback = (msg: string) => void;
type A = (a: string, b: Callback) => void;
type B = ExcludeLastParam<A>;
// type B = (a: string) => void
还有:
type C = (a: string, b: number, c: boolean, d: Date) => string;
type D = ExcludeLastParam<C>;
// type D = (a: string, b: number, c: boolean) => string
看起来很不错!
请注意,您的版本不起作用,因为虽然ParametersParameters<A>
的类型是[a: string, b: Callback]
,过滤掉Callback
不会起任何作用(因为Parameters<A>
不是联合类型...或者它是单成员联合,而该成员无法赋值给Callback
)。
英文:
You can use conditional type inference to exclude the last parameter from a function type:
type ExcludeLastParam<T extends (...args: any) => any> =
T extends (...args: [...infer I, any]) => infer R ? (...args: I) => R : never;
This matches T
against (...args: [...I, any]) => R
for some I
and R
that the compiler infers using the infer
keyword. Note that [...I, any]
is a variadic tuple type and by matching [...I, any]
against a tuple type (like, say, [a: string, b: Callback]
), the compiler will infer I
to be the "initial" part of the tuple excluding the last entry (since the any
type will match anything) (like, say, [a: string]
).
Let's test it out:
type Callback = (msg: string) => void;
type A = (a: string, b: Callback) => void;
type B = ExcludeLastParam<A>;
// type B = (a: string) => void
And
type C = (a: string, b: number, c: boolean, d: Date) => string;
type D = ExcludeLastParam<C>
// type D = (a: string, b: number, c: boolean) => string
Looks good!
Note that your version doesn't work because, while the Parameters<T>
utility type can be used to extract the parameter list as a tuple type, the Exclude<T, U>
utility type does not filter tuple types; instead it filters union types. Since Parameters<A>
is of type [a: string, b: Callback]
, filtering out Callback
isn't going to do anything (because Parameters<A>
is not a union... or maybe it's a single member union, and that member is not assignable to Callback
).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论