在Typescript

时间:2018-06-09 22:50:44

标签: typescript pattern-matching

采用以下最小例子:

type BinaryOp = 'MOV'
type UnaryOp = 'ADD' | 'SUB' | 'JRO'
const BinaryOps: BinaryOp[] = ['MOV']
const UnaryOps: UnaryOp[] = ['ADD', 'SUB', 'JRO']

type Line =
    { op: BinaryOp, a: number, b: number }
  | { op: UnaryOp, a: number }

以下“模式匹配”:

switch (line.op) {
    case 'ADD':
    case 'SUB':
    case 'JRO':
        return `${line.op} ${line.a}`
    case 'MOV':
        return `${line.op} ${line.a}, ${line.b}`
}

我不是特别喜欢这样,为了让案例理解op是UnaryOpBinaryOp,我必须列举所有可能性。有没有紧凑的(呃)方法来实现这个目标?

注意。请注意,这是一个简化的示例,可能还有其他类型的Op

1 个答案:

答案 0 :(得分:2)

我不相信可以使用任何TypeScript技巧来避免必须枚举所有case标签,因为标签必须是值 - 而不是类型。

但是,您可以使用if语句而不是switch语句,并且可以在if表达式中使用user-defined type guards

用户定义的类型保护是一种函数,其返回类型是类型谓词。例如,UnaryOp的用户定义类型保护可能如下所示:

function isUnaryOp(op: string): op is UnaryOp {
  return op && UnaryOps.includes(op as any);
}

if语句中使用时,用户定义的类型保护会缩小类型:

if (isUnaryOp(line.op)) {
  const op = line.op; // Inferred to be UnaryOp
} else if (isBinaryOp(line.op)) {
  const op = line.op; // Inferred to be BinaryOp
} else {
  const op = line.op; // Inferred to be never
}