Кортежи — это более легкая альтернатива объектам, когда вы хотите сгруппировать данные, поскольку для различения элементов используются позиции, а не имена свойств. Однако до сих пор кортежным типам не хватало многих полезных функций, предоставляемых объектными типами!
- Маркированные элементы кортежа:
type T = [foo: number, bar: string] - Аннотации отклонений (только для чтения/только для записи) для элементов кортежа:
type T = [+foo: number, -bar: string] - Необязательные элементы кортежа:
type T = [foo?: number, bar?: string] - Распространение кортежа
type T = [number, string, ...OtherTuple] - Уточнение длины кортежа
Прочтите полную документацию.
Маркированные элементы кортежа
Теперь вы можете добавить метку к элементам кортежа. Метки не влияют на тип элемента кортежа, но полезны для самостоятельного документирования назначения элементов кортежа, особенно когда несколько элементов имеют один и тот же тип.
type Range = [x: number, y: number];
Метки также необходимы для добавления к элементам аннотаций отклонений или модификаторов необязательности.
Аннотации отклонений для элементов кортежа и кортежей, доступных только для чтения.
Вы можете добавлять аннотации дисперсия (для обозначения только для чтения/только для записи) к помеченным элементам кортежа, как и к свойствам объекта:
type T = [+foo: number, -bar: string];
Это позволяет помечать элементы как доступные только для чтения или только для записи. Например:
function f(readOnlyTuple: [+foo: number, +bar: string]) {
const n: number = readOnlyTuple[0]; // OK to read
readOnlyTuple[1] = 1; // ERROR! Cannot write
}
Вы также можете использовать $ReadOnly для типов кортежей как сокращение для обозначения каждого свойства как доступного только для чтения:
type T = $ReadOnly<[number, string]>; // Same as `[+a: number, +b: string]`
Необязательные элементы кортежа
Вы можете пометить элементы кортежа как необязательные с помощью ? после метки элемента. Это позволяет опустить необязательные элементы. Необязательные элементы должны находиться в конце типа кортежа после всех обязательных элементов.
type T = [foo: number, bar?: string]; ([1, "s"]: T); // OK: has all elements ([1]: T); // OK: skipping optional element
Вы не можете записать undefined в необязательный элемент — добавьте | void к типу элемента, если хотите:
type T = [foo?: number, bar?: number | void]; declare const x: T; x[0] = undefined; // ERROR ([undefined]: T); // ERROR x[1] = undefined; // OK: we've added `| void` to the element type
Вы также можете использовать типы утилит Partial и Required, чтобы сделать все элементы необязательными или обязательными соответственно:
type AllRequired = [number, string]; ([]: Partial<AllRequired>); // OK: like `[a?: number, b?: string]` now type AllOptional = [a?: number, b?: string]; ([]: Required<AllOptional>); // ERROR: like `[a: number, b: string]` now
Кортежи с необязательными элементами имеют арность (длину), которая представляет собой диапазон, а не одно число. Например, [number, b?: string] имеет длину 1–2.
Распространение типа кортежа
Вы можете разделить тип кортежа на другой тип кортежа, чтобы создать более длинный тип кортежа:
type A = [number, string]; type T = [...A, boolean]; // Same as `[number, string, boolean]` ([1, "s", true]: T); // OK
Спреды кортежей сохраняют дисперсию и опциональность. Вы не можете разбивать массивы на кортежи, только на другие кортежи.
Уточнение по длине
Вы можете уточнить объединение кортежей по их длине:
type Union = [number, string] | [boolean];
function f(x: Union) {
if (x.length === 2) {
// `x` is `[number, string]`
const n: number = x[0]; // OK
const s: string = x[1]; // OK
} else {
// `x` is `[boolean]`
const b: boolean = x[0];
}
}
Технически это не новая функция, о которой ранее не сообщалось.
Принятие
Чтобы использовать помеченные элементы кортежа (включая необязательные элементы и аннотации отклонений к элементам) и элементы расширения кортежа, вам необходимо обновить свою инфраструктуру, чтобы она поддерживала синтаксис:
flowиflow-parser: 0,212,0prettier: 3babelсbabel-plugin-syntax-hermes-parser. Инструкции по настройке см. в нашем руководстве по Babel.eslintсhermes-eslint. Инструкции по настройке см. в нашем руководстве по ESLint.
Бонус: declare const и declare let
Flow теперь поддерживает declare const и declare let (в дополнение к существующему declare var). Они позволяют вам объявить переменную с типом, но без реализации. Они полезны для написания определений библиотек или создания воспроизведений проблем в Try Flow при использовании современных const и let вместо устаревших var. И declare const, и declare let являются блочными, как и их эквиваленты, отличные от declare.
if (cond) {
declare const foo: number;
}
foo; // ERROR: cannot resolve `foo` (as it's block-scoped)