[英]Infer typescript function arguments
Given the following鉴于以下
const action1 = (arg1: string) => {}
const action2 = (arg1: string, arg2: {a: string, b: number}) => {}
const actions = [action1, action2]
handleActions(actions)
... elsewhere ...
const handleActions = (actions: WhatTypeIsThis[]) => {
const [action1, action2] = actions;
action1(/** infer string */)
action2(/** infer string and object */)
}
How can I define the WhatTypeIsThis
type in order for the action args to be inferable inside handleActions
?如何定义
WhatTypeIsThis
类型以使操作 args 在handleActions
中可推断?
Is it possible to define it in such a way that actions
can be any number of functions with varying argument lists?是否可以将其定义为
actions
可以是具有不同参数列表的任意数量的函数?
Is it possible using generics?是否可以使用 generics?
Is it possible to define it in such a way that actions can be any number of functions with varying argument lists?
是否可以将其定义为动作可以是具有不同参数列表的任意数量的函数?
With a dynamic list, you need runtime checking.使用动态列表,您需要运行时检查。 I don't think you can do runtime checking on these functions without branding them (I tried doing it on
length
since those two functions have different lengths, but it didn't work and it really wouldn't have been useful even if it had — (arg1: string) => void
and (arg1: number) => void
are different functions with the same length
).我不认为你可以在不标记它们的情况下对这些函数进行运行时检查(我尝试对
length
进行检查,因为这两个函数有不同的长度,但它不起作用,即使它确实没有用— (arg1: string) => void
和(arg1: number) => void
是具有相同length
的不同函数)。
With branding and a runtime check, it's possible:通过品牌和运行时检查,可以:
handleActions
branch on the brandhandleActions
分支Like this:像这样:
type Action1 = (
(arg1: string) => void
) & {
__action__: "action1";
};
type Action2 = (
(arg1: string, arg2: {a: string, b: number}) => void
) & {
__action__: "action2";
};
const action1: Action1 = Object.assign(
(arg1: string) => {},
{__action__: "action1"} as const
);
const action2: Action2 = Object.assign(
(arg1: string, arg2: {a: string, b: number}) => {},
{__action__: "action2"} as const
);
const actions = [action1, action2];
type ActionsList = (Action1 | Action2)[];
const handleActions = (actions: ActionsList) => {
const [action1, action2] = actions;
if (action1.__action__ === "action1") {
action1("x"); // <==== infers `(arg: string) => void` here
}
};
handleActions(actions);
Before you added the text quoted at the top of the answer, it was possible with a readonly tuple type .在添加答案顶部引用的文本之前,可以使用 readonly tuple type 。 I'm keeping this in the answer in case it's useful to others, even though it doesn't apply to your situation.
我将其保留在答案中,以防它对其他人有用,即使它不适用于您的情况。
Here's what that looks like:看起来是这样的:
type ActionsList = readonly [
(arg1: string) => void,
(arg1: string, arg2: { a: string; b: number; }) => void
];
To make it readonly, you'll need as const
on actions
:要使其只读,您需要
as const
on actions
:
const actions = [action1, action2] as const;
// ^^^^^^^^^
A tuple is a kind of "...Array type that knows exactly how many elements it contains, and exactly which types it contains at specific positions."元组是一种“...数组类型,它确切地知道它包含多少元素,以及它在特定位置包含哪些类型。” (from the link above)
(来自上面的链接)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.