Выражения и инструкции match
match входное значение с рядом шаблонов, которые условно проверяют структуру входных данных и извлекают значения, а затем либо возвращают выражение (match выражения), либо выполняют блок (match инструкции).
Вы можете заменить инструкции switch с помощью match, избежав проблем, связанных с switch (например, перехода к следующей ветви), и получив такие преимущества, как проверка полноты и поддержка сложных шаблонов.
Вы также можете заменить вложенные условные тернарные выражения выражениями match, сделав код гораздо более понятным и получив возможности match.
import * as React from 'react';
component AgePane(
maybeAge?: {type: 'valid', age: number} | {type: 'error', msg: string}
) {
return match (maybeAge) {
{type: 'valid', const age} if (age < 0) =>
<Err>Age cannot be negative!</Err>,
{type: 'valid', const age} => <Pane>Age: {age}</Pane>,
{type: 'error', const msg} => <Err>{msg}</Err>,
undefined => <Err>Age is not defined.</Err>,
};
}
component Err(children: React.Node) { return <div>{children}</div>; }
component Pane(children: React.Node) { return <div>{children}</div>; } match доступно только в Flow — в TypeScript нет встроенной конструкции сопоставления с образцом. Полное сравнение см. в разделе «Выражения и инструкции match».
Выражения match
Выражения match позволяют задавать условную логику в виде выражения. Они могут заменить вложенные условные тернарные выражения.
Выражение match состоит из аргумента и ряда вариантов, каждый из которых задаёт шаблон и тело выражения. Шаблоны проверяются по очереди, а результатом становится выражение, соответствующее совпавшему шаблону. Тип результата — объединение типов всех выражений вариантов.
После шаблона можно указать условие с помощью синтаксиса if (<cond-expression>). Если шаблон совпадает, также вычисляется выражение условия, и весь вариант считается совпавшим только в том случае, если результат является истинным.
Пример структуры:
const e = match (<arg>) {
<pattern-1> => <expression-1>,
<pattern-2> if (<cond>) => <expression-2>,
<pattern-3> => <expression-3>,
}; Условие применяется ко всему шаблону, включая шаблоны «или». Например, 1 | 2 if (cond) сначала даст совпадение, если значение равно 1 | 2, а окончательно совпадёт, только если cond также истинно. Варианты с условием не учитываются при проверке полноты, поскольку совпадение может зависеть от условия.
Вы можете инициализировать две или более переменных с помощью match — например, кортежем:
enum Status {Active, Paused, Off}
declare const status: Status;
const [color, size] = match (status) {
Status.Active => ['green', 2],
Status.Paused => ['yellow', 1],
Status.Off => ['red', 0],
}; или объектом (особенно удобно для более чем двух переменных):
enum Status {Active, Paused, Off}
declare const status: Status;
const {color, size} = match (status) {
Status.Active => {color: 'green', size: 2},
Status.Paused => {color: 'yellow', size: 1},
Status.Off => {color: 'red', size: 0},
}; Выражения match нельзя использовать в позиции оператора-выражения, поскольку она предназначена для инструкций match.
match (<arg>) {} // This is a match statement, not a match expression Если ни один шаблон не совпадёт, Flow выдаст ошибку из-за неполного сопоставления, а во время выполнения будет выброшено исключение. В качестве последнего варианта match можно использовать шаблон-универсал (_) или шаблон объявления переменной (const x), чтобы обработать все оставшиеся возможные совпадения.
Чтобы выбросить исключение в теле варианта выражения match, нельзя использовать throw, поскольку это инструкция, а выражения match требуют тела-выражения. Вместо этого можно использовать invariant(false, <msg>), которое Flow понимает как выражение, всегда выбрасывающее исключение с указанным сообщением.
Тела вариантов выражений match пока не поддерживают использование yield, yield* или await. В отличие от выражений match, инструкции match поддерживают эти ключевые слова.
Примечание: Открывающая фигурная скобка { должна находиться в той же строке, что и аргумент match match (<arg>). Благодаря этому мы можем добавить эту возможность, сохранив обратную совместимость со всем существующим синтаксисом: match(x); по-прежнему является вызовом функции с именем match. Prettier автоматически форматирует выражения match таким образом.
Инструкции match
Инструкции match могут заменить инструкции switch или цепочки инструкций if-else. Как и выражения match, они содержат аргумент и ряд вариантов. Разница в том, что тело каждого варианта представляет собой блок (то есть { ...statements... }), а не выражение; кроме того, эта конструкция является инструкцией и поэтому не возвращает значение. break не требуется: выполнение не переходит к следующему варианту (но вы по-прежнему можете объединять несколько шаблонов, используя шаблоны «или» |).
Пример структуры:
match (<arg>) {
<pattern-1> => {
<statements-1>;
}
<pattern-2> if (<cond>) => {
<statements-2>;
}
<pattern-3> => {
<statements-3>;
}
} Примечание: Как и в выражениях match, открывающая фигурная скобка { должна находиться в той же строке, что и аргумент match match (<arg>).
Проверка полноты
match требует учесть все возможные варианты входных данных. Если этого не сделать, Flow выдаст ошибку [match-not-exhaustive] и укажет конкретные шаблоны, которые нужно добавить, чтобы сопоставление было полным. Это особенно полезно, когда тип входных данных меняется: добавление нового варианта в объединение выявляет все места сопоставления, где он не обработан. Так незаметный переход к следующей ветви во время выполнения превращается в локальную ошибку типа.
declare const tab: 'home' | 'details' | 'settings';
match (tab) { // ERROR [match-not-exhaustive]
'home' => {}
'settings' => {}
} Поддерживается проверка непересекающихся объединений объектов.
declare const result: {type: 'ok', value: number} | {type: 'error'};
match (result) { // ERROR
{type: 'error'} => {}
} Это работает даже для вложенных структур:
function getStyle(
align: 'start' | 'end',
position: 'above' | 'below',
) {
return match ([align, position]) { // ERROR
['start', 'above'] => 0,
['start', 'below'] => 1,
['end', 'above'] => 2,
};
} Flow также выдаст ошибку, если шаблон не используется:
declare const tab: 'home' | 'details' | 'settings';
match (tab) {
'home' => {}
'details' => {}
'settings' => {}
'invalid' => {} // ERROR
} Дополнительно
Подробнее о шаблонах match, включая шаблоны примитивных значений, массивов и объектов, шаблоны объявления переменных, а также шаблоны «или» и «как».
Вы также можете перейти с существующих конструкций, например switch или условных тернарных выражений.
Подключение
- Flow: включено по умолчанию начиная с Flow v0.317. В более ранних версиях добавьте
pattern_matching=trueв.flowconfig, в разделе[options].- Шаблоны экземпляров проверяются по типам по умолчанию начиная с Flow v0.317.
- Babel: используйте flow-parser/babel-plugin; подробности см. в нашем руководстве по Babel.
- ESLint: используйте flow-eslint; подробности см. в нашем руководстве по ESLint.
См. также
- Объединения — часто сопоставляются с непересекающимися объединениями
- Перечисления Flow — перечисления хорошо сочетаются с выражениями match при проверке полноты
© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/match