我希望打字稿接受具有相似结构但具有不同值的参数列表,并正确推断生成的联合类型。
示例代码
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 的解决方案很好地解决了之前版本中所述的问题,但是我的示例缺少一些使其适用于我的实际代码的东西,即当函数的参数必须与其他地方定义的类型匹配时。