Сопоставление с возможными литералами типов в Typescript - PullRequest
0 голосов
/ 10 июня 2018

Возьмите следующий минимальный пример:

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

Мне это не особо нравится, чтобы кейс понялОперация UnaryOp или BinaryOp, я должен перечислить все возможности.Есть ли компактный (er) способ добиться этого?

ПРИМЕЧАНИЕ. Учтите, что это упрощенный пример, и могут существовать другие виды Op.

1 Ответ

0 голосов
/ 10 июня 2018

Я не верю, что есть какая-то хитрость TypeScript, которую можно использовать, чтобы избежать необходимости перечислять все метки case, поскольку метки должны быть значениями, а не типами.

Однако,вы могли бы использовать if операторы вместо switch и вы могли бы использовать определяемые пользователем типы защиты в выражениях if.

определяемая пользователем защита типа является функциейимеет возвращаемый тип, который является предикатом типа.Например, определяемый пользователем тип защиты для 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
}
...