如何在项目中为库定义的CommandHandler联合类型追加类型?
实现方案:在库中定义基础
CommandHandler,项目中扩展类型 当然可以实现!TypeScript的类型系统提供了几种灵活的方式来让你在库中定义一个“基础版”的CommandHandler,然后在业务项目中扩展它的类型,刚好匹配你的需求。下面我给你两种最贴合场景的方案:
方案一:用可扩展的联合类型(贴合原需求的联合类型结构)
这种方式最直接,因为你原本的CommandHandler就是联合类型,我们可以在库中把它定义为一个空的联合类型(never),然后在项目中把需要的类型追加进去。
库中的代码(library.ts)
export type Command = { AggregateId: string }; // 基础版CommandHandler:默认是空的联合类型(never表示没有任何有效类型) export type CommandHandler = never; // 导出项目需要用到的具体命令处理类型 export type AddUser = (command: Command) => Promise<{ streamId: string }>; export type RemoveUser = (command: Command) => Promise<{ streamId: string }>;
项目中的代码(project.ts)
import { CommandHandler as BaseHandler, AddUser, RemoveUser } from './library'; // 扩展基础类型,把AddUser和RemoveUser追加到CommandHandler中 export type CommandHandler = BaseHandler | AddUser | RemoveUser; // 现在使用CommandHandler就包含了两种命令处理函数的类型 const addUserHandler: CommandHandler = async (command) => { return { streamId: `user-${command.AggregateId}` }; }; const removeUserHandler: CommandHandler = async (command) => { return { streamId: `removed-${command.AggregateId}` }; };
方案二:用接口声明合并(适合需要扩展属性/重载的场景)
如果你更倾向于用接口的方式来管理类型,TypeScript的接口声明合并特性可以让你在项目中直接扩展库中定义的空接口。
库中的代码(library.ts)
export type Command = { AggregateId: string }; // 定义一个开放的空接口,允许外部项目合并扩展 export interface CommandHandler {} // 导出项目需要的具体命令处理类型 export type AddUser = (command: Command) => Promise<{ streamId: string }>; export type RemoveUser = (command: Command) => Promise<{ streamId: string }>;
项目中的代码(project.ts)
import { CommandHandler, AddUser, RemoveUser } from './library'; // 通过模块声明合并,把AddUser和RemoveUser的类型合并到CommandHandler中 declare module './library' { // 让CommandHandler成为AddUser和RemoveUser的联合类型 type CommandHandler = AddUser | RemoveUser; } // 测试使用 const handler: CommandHandler = async (command) => { return { streamId: command.AggregateId }; };
方案选择建议
- 如果你希望保持
CommandHandler作为联合类型的原有结构,优先选方案一,代码更直观,贴合你的初始需求; - 如果你后续需要给
CommandHandler添加属性或者重载签名,方案二的接口合并会更灵活。
内容的提问来源于stack exchange,提问作者Alexander Zeitler
相关产品推荐
相关产品推荐

