将方法签名限制为仅允许事件映射中定义的类型的有效负载
Restrict method signature to only allow payload of type defined in event map
我正在开发一个事件 (pub/sub) 系统,我需要预先定义事件和有效负载。无法将 publish
方法限制为 EVENT,EVENT[PAYLOAD]。
// This is the closest I got to, but it isn't working:
class SomeClass<EVENT_MAP, EVENTNAME extends keyof EVENT_MAP> {
publish(eventName: EVENTNAME, payload: EVENT_MAP[EVENTNAME]) {}
}
enum EVENTS {
HELLO,
WORLD
}
type EVENT_SIGNATURES = {
[EVENTS.HELLO]: {
messageId: string
},
[EVENTS.WORLD]: {
age: number
}
}
// This does not work as expected. What am I doing wrong?
const someClass = new SomeClass<EVENT_SIGNATURES, keyof EVENT_SIGNATURES>();
// Here's how I expect it work:
someClass.publish(EVENTS.HELLO, { messageId: 123 }) // => error. string expected
someClass.publish(EVENTS.HELLO, { messageId: "123", age: 15 }); // => error. age shouldn't be on here
someClass.publish(EVENTS.HELLO, { messageId: '123' }) // => good
someClass.publish(EVENTS.WORLD, { messageId: '123' }) // => error. messageId isn't on the type
someClass.publish(EVENTS.WORLD, { age: 123 }) // => good
// Here's what actually happens
someClass.publish(EVENTS.HELLO, { messageId: 123 }); // => error. string expected
someClass.publish(EVENTS.HELLO, { messageId: "123", age: 15 }); good
someClass.publish(EVENTS.HELLO, { messageId: "123" }); // => good
someClass.publish(EVENTS.WORLD, { messageId: "123" }); // => good
someClass.publish(EVENTS.WORLD, { age: 123 }); // => good
这是打字稿推断出的签名:
(method) SomeClass<EVENT_SIGNATURES, EVENTS>.publish(eventName: EVENTS, payload: {
messageId: string;
} | {
age: number;
}): void
而我需要将有效负载限制为 EVENTNAME。
这里还有一个沙盒:https://codesandbox.io/s/bold-joliot-1bi9m?file=/src/index.ts:591-693
提前致谢!
尝试使 publish 通用,记住传入的 eventName
:
class SomeClass<EVENT_MAP> {
publish<EVENTNAME extends keyof EVENT_MAP>(eventName: EVENTNAME, payload: EVENT_MAP[EVENTNAME]) {}
}
我正在开发一个事件 (pub/sub) 系统,我需要预先定义事件和有效负载。无法将 publish
方法限制为 EVENT,EVENT[PAYLOAD]。
// This is the closest I got to, but it isn't working:
class SomeClass<EVENT_MAP, EVENTNAME extends keyof EVENT_MAP> {
publish(eventName: EVENTNAME, payload: EVENT_MAP[EVENTNAME]) {}
}
enum EVENTS {
HELLO,
WORLD
}
type EVENT_SIGNATURES = {
[EVENTS.HELLO]: {
messageId: string
},
[EVENTS.WORLD]: {
age: number
}
}
// This does not work as expected. What am I doing wrong?
const someClass = new SomeClass<EVENT_SIGNATURES, keyof EVENT_SIGNATURES>();
// Here's how I expect it work:
someClass.publish(EVENTS.HELLO, { messageId: 123 }) // => error. string expected
someClass.publish(EVENTS.HELLO, { messageId: "123", age: 15 }); // => error. age shouldn't be on here
someClass.publish(EVENTS.HELLO, { messageId: '123' }) // => good
someClass.publish(EVENTS.WORLD, { messageId: '123' }) // => error. messageId isn't on the type
someClass.publish(EVENTS.WORLD, { age: 123 }) // => good
// Here's what actually happens
someClass.publish(EVENTS.HELLO, { messageId: 123 }); // => error. string expected
someClass.publish(EVENTS.HELLO, { messageId: "123", age: 15 }); good
someClass.publish(EVENTS.HELLO, { messageId: "123" }); // => good
someClass.publish(EVENTS.WORLD, { messageId: "123" }); // => good
someClass.publish(EVENTS.WORLD, { age: 123 }); // => good
这是打字稿推断出的签名:
(method) SomeClass<EVENT_SIGNATURES, EVENTS>.publish(eventName: EVENTS, payload: {
messageId: string;
} | {
age: number;
}): void
而我需要将有效负载限制为 EVENTNAME。
这里还有一个沙盒:https://codesandbox.io/s/bold-joliot-1bi9m?file=/src/index.ts:591-693
提前致谢!
尝试使 publish 通用,记住传入的 eventName
:
class SomeClass<EVENT_MAP> {
publish<EVENTNAME extends keyof EVENT_MAP>(eventName: EVENTNAME, payload: EVENT_MAP[EVENTNAME]) {}
}