typescript - 来自对象属性的动态 Typescript 函数参数
问题描述
我想要一个函数,它返回一个新函数,其类型取决于传递给包装函数的参数。包装函数应该将函数和对象作为参数。以下是一些类型信息:
type Event = {};
type EventExecutor<T extends Event> = (event: T) => void;
type EventMap<T extends Event> = {
[id: string]: (...args: any) => T;
};
并且该功能将实现如下:
function createEventHandler<
T extends Event,
M extends EventMap<T>,
K extends keyof M
>(executor: EventExecutor<T>, eventMap: M) {
return (id: K, ...params: Parameters<M[K]>) => {
const event = eventMap[id](...params);
executor(event);
};
}
我期望它的工作方式是:
type MyEventA = { type: 'foo', fizz: string };
type MyEventB = { type: 'bar', buzz: number };
type MyEvent = MyEventA | MyEventB;
function myEventExecutor(event: MyEvent) {
// ...
}
const myEventMap = {
hello: (p: string) => ({ type: 'foo', fizz: p }),
goodbye: (n: number) => ({ type: 'bar', buzz: n }),
};
const myHandler = createEventHandler(myEventExecutor, myEventMap);
myHandler('hello', 'world'); // correct
myHandler('goodbye', 42); // correct
myHandler('hello', 42); // ERROR
myHandler('goodbye', 'world'); // ERROR
myHandler('wrong', 'stuff'); // ERROR
我目前有一些问题。一个似乎我丢失了id
in的所有类型信息myHandler
......任何字符串都没有错误地传递。参数也一样。
我真的不确定问题是什么,因为类型信息似乎有意义???
此外,我希望能够让事件映射成为返回泛型的函数Event
或只是那个泛型Event
(换句话说,一个静态事件)Event | (...args: any) => Event
......但如果我不能要做到这一点。
解决方案
我认为您缺少的是返回值createEventHandler()
本身应该是一个通用函数,如下所示:
function createEventHandler<
T extends Event,
M extends EventMap<T>,
K extends keyof M
>(executor: EventExecutor<T>, eventMap: M) {
return <P extends K>(id: P, ...params: Parameters<M[P]>) => {
const event = eventMap[id](...params);
executor(event);
};
}
然后,您还需要确保您的类型myEventMap
尽可能窄(以便type
键入 as'foo'
而不是 as string
)。如果您使用的是 TS3.4+,则可以使用const
断言:
const myEventMap = {
hello: (p: string) => ({ type: 'foo', fizz: p } as const),
goodbye: (n: number) => ({ type: 'bar', buzz: n } as const),
};
否则,您可以通过多种方式解决它(例如{type: 'foo' as 'foo', fizz: p}
)。
鉴于这些更改,您将获得您正在寻找的行为:
myHandler('hello', 'world'); // correct
myHandler('goodbye', 42); // correct
myHandler('hello', 42); // ERROR
myHandler('goodbye', 'world'); // ERROR
myHandler('wrong', 'stuff'); // ERROR
希望有帮助;祝你好运!
推荐阅读
- javascript - 在 React 中使用 enter 提交输入字段?
- react-native - 我们如何在 React Native 中实现身份验证同步?
- xamarin - Is there anything to be gained by upgrading Rg.Plugins.Popup from release: 1.2.0.223 to 2.0.0.2 when used in Xamarin Forms?
- javascript - 等待异步数据后将 AngularFire 数据绑定到属性
- c# - 如何确定字符串是 NT 帐户还是安全标识符?
- powershell - 如何使用不同的凭据和 runas 运行 scriptblock?
- apache-spark - 在运行时更改 PySpark 的配置
- python - K 均值算法应该运行这么长时间吗?
- php - PHP - 布尔回复未按预期工作
- r - 估计 R 中的概率分布