在打字稿的列表中映射正确函数的函数签名

  • 本文关键字:函数 映射 列表 typescript
  • 更新时间 :
  • 英文 :


我正在构建一个消息格式化程序,它可以构建一堆不同类型的消息。根据它正在构建的消息类型,将调用不同的呈现函数。这些函数中的每一个都可以接受不同的参数或可选参数。

我在设置这个并让打字稿理解我在做什么时遇到问题。

这里有一些混乱的代码,让你了解我想要什么。

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"

上面的代码存在一些问题。例如,我在为getFormattedMessagemessageBuilders正确设置打字稿签名时遇到问题。

我想达到这样的地步:如果我在编辑器中键入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),因为我没有找到解决方案作为读者的练习。

游乐场链接

最新更新