英文:
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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论