繁体   English   中英

TypeScript区分了与泛型的联合

[英]TypeScript discriminated union with generics

有没有一种方法可以建立一个区分工会,让您与每个工会成员一起捕获特定类型? 我试图按照以下方式编写类型安全的命令处理程序:

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中实现呢?

您可以通过使用捕获捕获的传入命令类型的重载和映射接口来在命令类型和结果类型之间创建关系(也可以使用结果联合,但是提取结果类型不会因缺少命令类型而导致错误,因此在这种情况下,我更喜欢映射接口。

我们无法确保实现中的返回类型直接对应于预期的返回类型。 我们能做的最好的就是在开关中使用一个额外的功能来验证这一点:


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))
    }
  }
}

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM