【发布时间】:2020-11-15 06:51:42
【问题描述】:
我希望 typescript 接受具有相似结构但具有不同值的参数列表,并正确推断生成的联合类型。
示例代码
interface User<
N extends string = string,
S extends unknown = unknown,
A extends (a: S) => unknown = (a: S) => unknown
> {
name: N;
state: S;
action: A;
}
function createUser<
N extends string = string,
S extends unknown = unknown,
A extends (a: S) => unknown = (a: S) => unknown
>(name: N, state: S, action: A): User<N, S, A> {
return { action, name, state };
}
function combineUsers<
V extends User<string, unknown, (a: unknown) => unknown>[]
>(...users: V) {
type Names = V[number]["name"];
return {
actions: users.reduce(
(a, u) => ({ ...a, [u.name]: u.action }),
{} as { [K in Names]: Extract<V[number], { name: K }>["action"] },
),
names: new Set<Names>(users.map((u) => u.name)),
};
}
const userA = createUser("user1", 1, (_a: number) => undefined);
const user2 = createUser("userB", "two", (_s: string) => true);
const users = combineUsers(userA, user2);
// Argument of type 'User<"user1", number, (_a: number) => undefined>' is not assignable to parameter of type 'User<string, unknown, (a: unknown) => unknown>'.
// Type '(_a: number) => undefined' is not assignable to type '(a: unknown) => unknown'.
// Types of parameters '_a' and 'a' are incompatible.
// Type 'unknown' is not assignable to type 'number'.ts(2345)
这是我得到的编译错误,因为不兼容的功能。
我希望看到函数返回的类型是一些推断的联合,例如;
type Return = {
names: Set<"user1" | "userB">,
actions: {
user1: (_a: number) => undefined;
userB: (_s: string) => boolean;
}
}
- 这甚至可能吗?可以洒
any,但我宁愿不要 - 是否有任何替代方案或更好的方法来实现这一目标
编辑:
@jcalz 的解决方案很好地解决了之前版本中所述的问题,但我的示例缺少一些使其适用于我的实际代码的东西,即当函数的参数必须与其他地方定义的类型匹配时。
【问题讨论】:
-
我对此有一个答案,但是...在
createUser()中,isfnArgs只是一个虚拟参数,用于向编译器提示action方法将采用的参数类型?它确实看起来像,但有什么意义,当有问题的方法无论如何都只会返回returnValue值时?为什么(...args: A)=>R的复杂性还不如只使用() => R?或者,为什么createUser实际上不采用(...args: A)=>R类型的函数 而不是A和R类型的值?这是一个奇怪/分散注意力的例子。可以修改吗? -
可以,可以修改。只是试图创建我的实际代码的精简版本。这个例子中的很多东西对于给出问题的上下文是多余的。
标签: javascript typescript typescript-typings