typescript - 如何在 TypeScript 中表达正确类型的消息队列?
问题描述
我正在探索如何在 TypeScript 中编写正确类型的消息队列,其中每个主题都由符号标识并具有自己的消息类型。我正在寻找以下形式的东西:
const names = Symbol('name');
const ages = Symbol('age');
type Name = string;
type Age = number;
type TopicId = Symbol;
interface Messager {
publish(topic: TopicId, message: any): Promise<boolean>,
subscribe(topic: TopicId, consumer: (message: any) => Promise<boolean>): void
}
const messager: Messager<NameTopic | AgeTopic> = null;
messager.publish(names, "test-name");
messager.publish(ages, 23);
以便发布和订阅方法的消息类型根据主题的类型进行区分。例如,我希望该messager
值是Messager
允许在主题上发布字符串和在name
主题上发布数字的类型的实例age
。
这感觉像是分布式条件类型的工作,但我担心正确的语法让我难以理解。
解决方案
我倾向于定义这样的事情:
type Topic = {
symbol: Symbol;
type: unknown
}
interface Messager<T extends Topic> {
publish<S extends T["symbol"]>(
topic: S,
message: Extract<T, { symbol: S }>["type"]
): Promise<boolean>,
}
所以 aTopic
是一对符号和类型。然后, aMessager
可以是泛型的T
,类型的联合Topic
。您的方法将是通用的S
,其中的符号之一T
(具体来说,您正在查找的"symbol"
属性T
,即 ,T["symbol"]
如果是联合,它将T
是联合)。
对于publish
,topic
参数只是S
。然后我们要将message
参数约束为相应的"type"
属性。这就是那些分布式条件类型的用武之地。在这里,我使用Extract<A, B>
了一个实用程序类型,它采用联合类型A
并只保留它的可分配给的成员B
。因此,如果我们采取Extract<T, {symbol: S}>
,我们应该只得到"symbol"
属性所在的主题S
。然后我们查找它的"type"
属性......给我们类型Extract<T, {symbol: S}>["type"]
。
让我们看看它的实际效果:
const names = Symbol('name');
type NameTopic = {
symbol: typeof names;
type: string
}
const ages = Symbol('age');
type AgeTopic = {
symbol: typeof ages;
type: number;
}
这里我们有两种Topic
类型,NameTopic
和AgeTopic
。其余代码按您的意愿进行:
const messager: Messager<NameTopic | AgeTopic> = null!;
messager.publish(names, "test-name"); // okay
messager.publish(names, 100); // error! 100 is not a string
messager.publish(ages, 23); // okay
messager.publish(ages, "NaN") // error! "NaN" is not a number
const shoesizes = Symbol("shoesizes")
messager.publish(shoesizes, 123); // error, not the right symbol
编译器强制正确的值与正确的符号一起使用。希望有帮助;祝你好运!
推荐阅读
- generics - 元组上 std::ops 的通用实现
- ruby-on-rails - 是否有一种配置可以清除 i18n 插值字符串的缓存(或者可能阻止缓存)?
- node.js - 如何使用 mongodb 更新双嵌套数组中的对象?
- python - 我想知道下面代码中 lambda x=x 的目的是什么?
- r - 日期和其他列作为 R 闪亮中的过滤器
- android - FileSystemNotFoundException:未安装提供程序“gs”(Android)
- reactjs - 故障映射反应带模态
- scala - Scala - PriorityQueue 的订购失败
- amazon-web-services - 如何在服务目录的 AWS CloudFormation 参数中列出所有私有 AMI
- tensorflow - refrigator tensorflow 的预训练或数据集