我正在构建一个消息格式化程序,它可以构建一堆不同类型的消息。根据它正在构建的消息类型,将调用不同的呈现函数。这些函数中的每一个都可以接受不同的参数或可选参数。
我在设置这个并让打字稿理解我在做什么时遇到问题。
这里有一些混乱的代码,让你了解我想要什么。
export enum MessageType {
Greeting,
Warning,
}
getFormattedMessage(messageType:MessageType, ...messageParams): string {
const messageBuilders: {[K in MessageType]: () => string} = {
[MessageType.Greeting]: () => 'Hi There',
[ErrorType.Warning]: ({name}) =>
name ? `${name} is required` : 'That thing is required',
}
return messageBuilders[messageType](...messageParams)
}
getFormattedMessage(MessageType.Greeting)
// output, "Hi There
getFormattedMessage(MessageType.Warning)
// output, "That thing is required"
getFormattedMessage(MessageType.Warning, {name: "A fancy hat"})
// output, "A fancy hat is required"
上面的代码存在一些问题。例如,我在为getFormattedMessage
或messageBuilders
正确设置打字稿签名时遇到问题。
我想达到这样的地步:如果我在编辑器中键入getFormattedMessage(MessageType.Warning,
,vsCode 将建议附加到Warning
类型的渲染函数签名中显示的变量,依此类推。
谢谢一堆!
这里使用了一个帮助器标识函数newMessageBuilder
,让编译器隐式推断 messageBuilder 的类型,同时约束其类型的下限;然后使用Parameters<(typeof messageBuilders)[K]>
根据messageType
的值约束messageParams
的类型。
export enum MessageType {
Greeting,
}
export enum ErrorType {
Warning = 1,
}
function newMessageBuilder<T extends {[K in MessageType | ErrorType]: (...messageParams: any[]) => string}>(messageBuilders: T) { return messageBuilders; }
const messageBuilders = newMessageBuilder({
[MessageType.Greeting]: () => 'Hi There',
[ErrorType.Warning]: ({name}: {name: string}) =>
name ? `${name} is required` : 'That thing is required',
});
function getFormattedMessage<K extends MessageType | ErrorType>(messageType: K, ...messageParams: Parameters<(typeof messageBuilders)[K]>) {
return (messageBuilders[messageType] as any)(...messageParams);
}
getFormattedMessage(MessageType.Greeting)
// output, "Hi There
// ERROR Argument of type '{ a: number; }' is not assignable to parameter of type '{ name: string; }'.
// Object literal may only specify known properties, and 'a' does not exist in type '{ name: string; }'.(2345)
getFormattedMessage(ErrorType.Warning, {a:1})
// output, "That thing is required"
getFormattedMessage(ErrorType.Warning, {name: "A fancy hat"})
// output, "A fancy hat is required"
当然,上述问题仍然存在,例如我忽略作为读者的练习。(messageBuilders[messageType] as any)
,因为我没有找到解决方案
游乐场链接