有没有一种方法可以建立一个可区分的联合,让您与每个联合成员一起捕获特定类型?我试图按照以下方式编写类型安全的命令处理程序:
interface GetUsersCommand { // returns User[]
type: 'GET_USERS'
}
interface UpdateUserNameCommand { // returns void
type: 'UPDATE_USER_NAME'
userId: string
name: string
}
type Command<Result> = GetUsersCommand | UpdateUserNameCommand
class CommandExecutor {
execute<Result>(command: Command<Result>): Result {
switch (command.type) {
case 'GET_USERS': return [ user1, user2, user3 ]
case 'UPDATE_USER_NAME': updateUserName(command.userId, command.name)
}
}
}
这个想法是CommandExecutor
不仅会在缩小范围后知道每个命令中的字段,而且还可以验证返回类型是否符合每个命令的要求。有没有在TypeScript中实现此目标的好模式?
答案 0 :(得分:2)
您可以通过使用重载来创建命令类型与结果类型之间的关系,该重载捕获传入的命令类型和映射接口(也可以使用结果并集,但是提取结果类型不会导致以下错误:缺少命令类型,因此在这种情况下,我倾向于使用映射接口。
我们不能确保实现中的返回类型直接对应于预期的返回类型。我们能做的最好的就是在开关中使用一个额外的功能来验证这一点:
interface GetUsersCommand { // returns User[]
type: 'GET_USERS'
}
interface CommandResults {
'GET_USERS': Users[]
}
interface UpdateUserNameCommand { // returns void
type: 'UPDATE_USER_NAME'
userId: string
name: string
}
interface CommandResults {
'UPDATE_USER_NAME': void
}
type Command = GetUsersCommand | UpdateUserNameCommand
function checkResult<T extends keyof CommandResults>(type: T, result: CommandResults[T]) {
return result;
}
class CommandExecutor {
execute<T extends Command>(command: T): CommandResults[T['type']]
execute(command: Command): CommandResults[keyof CommandResults] {
switch (command.type) {
case 'GET_USERS': return checkResult(command.type, [ user1, user2, user3 ])
case 'UPDATE_USER_NAME': return checkResult(command.type, updateUserName(command.userId, command.name))
}
}
}