Const-выражения
Модификатор as const указывает Flow выводить максимально узкий тип для литерального выражения — литеральные типы для примитивов и типы только для чтения для контейнеров.
const x = 42 as const; // type is 42, not number
const a = [1, 2] as const; // type is Readonly<[1, 2]>, not Array<number>
const o = {x: 1} as const; // type is Readonly<{x: 1}>, not {x: number} Когда это использовать
Используйте as const, когда Flow должен сохранять точные литеральные значения и структуру только для чтения — например, чтобы сохранить конкретные строковые значения в объекте конфигурации или гарантировать, что массив рассматривается как кортеж фиксированной длины. Если нужно лишь сделать литерал массива или объекта доступным только для чтения, не сужая его до литеральных типов, используйте вместо этого утилитарный тип Readonly.
Типизация const-выражений
Для примитивных значений выводимый тип const-выражений — это синглтонный тип, а для типов-контейнеров — их версии только для чтения. Литералы массивов выводятся как типы кортежей.
Вот несколько примеров примитивных значений:
42 as const; // inferred type is 42 "hello" as const; // inferred type is "hello"
Контейнеры становятся доступными только для чтения, а модификатор применяется глубоко
const o1 = {f: 42} as const; // {readonly f: 42}
const t1 = [42, "hello"] as const; // Readonly<[42, "hello"]>
const o2 = {f: {g: 42}} as const; // {readonly f: {readonly g: 42}} Обратите внимание, что действие модификатора не сохраняется при передаче через переменные. Например, в этом случае
const nonConstObject = { g: 42 };
const constObject = { f: nonConstObject } as const; тип nonConstObject будет {g: number}, а тип constObject — {readonly f: {g: number}}. Другими словами, только свойство верхнего уровня f будет доступно только для чтения.
Наконец, as const работает непосредственно с литералами, а также с переменными const, инициализированными примитивным литералом. Его применение к другим выражениям — например, к значению, считанному из привязки let, — приведёт к ошибке:
let x = 1; const y = x as const; // Error
Типичный пример const-выражения
Распространённый случай применения const-выражений — структуры, похожие на enum, которые не предполагается изменять. Например:
export const STATUS = {
INIT: 'INIT',
LOADING: 'LOADING',
SUCCESS: 'SUCCESS',
ERROR: 'ERROR',
} as const; Тип STATUS.INIT — это "INIT", тип STATUS.LOADING — это "LOADING" и так далее.
При таком определении также можно фактически использовать значения различных полей в аннотациях типов. Например:
const STATUS = {
INIT: 'INIT',
LOADING: 'LOADING',
SUCCESS: 'SUCCESS',
ERROR: 'ERROR',
} as const;
type State =
| { readonly kind: typeof STATUS.INIT; }
| { readonly kind: typeof STATUS.LOADING; progress: number; }
| { readonly kind: typeof STATUS.SUCCESS; result: string; }
| { readonly kind: typeof STATUS.ERROR; msg: string; }; Без использования as const тип typeof STATUS.INIT был бы string, что сделало бы его непригодным в качестве различающего тега в дизъюнктивном объединении.
Const-выражения для React JSX
Если вы не знакомы с типизацией React в Flow, ознакомьтесь с разделами типы render и справочник по типам React.
По умолчанию Flow выводит для элементов React JSX более общий тип.
import * as React from 'react'; const div1 = <div />; // `<div />` has type `React.MixedElement` declare component Foo(); const foo1 = <Foo />; // `<Foo />` has type `renders Foo`
Однако если JSX-элемент находится в позиции, для которой возможна контекстная типизация, Flow выведет более конкретный тип, благодаря чему элемент можно будет передать в API с более строгими требованиями:
import * as React from 'react';
type ExactDiv = ExactReactElement_DEPRECATED<'div'>;
declare function onlyAllowsExactDiv(div: ExactDiv): void;
declare component OnlyAllowsExactDiv(children: ExactDiv);
const divGeneral = <div />;
onlyAllowsExactDiv(divGeneral); // Error
<OnlyAllowsExactDiv>{divGeneral}</OnlyAllowsExactDiv>; // Error
onlyAllowsExactDiv(<div />); // OK
<OnlyAllowsExactDiv><div /></OnlyAllowsExactDiv>; // OK Если нужно, чтобы JSX-элемент имел более конкретный тип в позиции, для которой невозможна контекстная типизация, его можно обернуть в as const:
import * as React from 'react';
type ExactDiv = ExactReactElement_DEPRECATED<'div'>;
declare function onlyAllowsExactDiv(div: ExactDiv): void;
declare component OnlyAllowsExactDiv(children: ExactDiv);
const divSpecific = <div /> as const;
onlyAllowsExactDiv(divSpecific); // OK
<OnlyAllowsExactDiv>{divSpecific}</OnlyAllowsExactDiv>; // OK Переход на синтаксис as const
Чтобы использовать синтаксис as const, необходимо обновить инструменты:
- Prettier: 3.1+
- Babel: используйте flow-parser/babel-plugin; подробнее см. в нашем руководстве по Babel.
- ESLint: используйте flow-eslint; подробнее см. в нашем руководстве по ESLint.
const параметры типа
Иногда полезно указать, что аргумент функции всегда должен быть const-выражением. В таких случаях можно аннотировать параметр типа модификатором const. Такие параметры типа называются const-параметрами типа.
В каких случаях полезны const параметры типа?
Например, если нужно гарантировать, что все аргументы, передаваемые функции foo с сигнатурой
declare function foo<X>(x: X): X;
будут обрабатываться как const-выражения. Один из способов обеспечить это — всегда вызывать foo, применяя as const к его аргументу:
declare function foo<X>(x: X): X;
const x1 = foo({ f: 42 } as const);
const x2 = foo([42, "hello"] as const); Переменные x1 и x2 будут иметь типы {readonly f: 42} и Readonly<[42, "hello"]> соответственно.
Чтобы не повторять as const и не забыть передать его, можно использовать модификатор const для параметра типа X:
declare function constFoo<const X>(x: X): X;
const y1 = constFoo({ f: 42 });
const y2 = constFoo([42, "hello"]); Переменные y1 и y2 будут иметь те же типы, что и x1 и x2 соответственно.
Переход на синтаксис const-параметров типа const
Чтобы использовать синтаксис const-параметров типа const, необходимо обновить инструменты:
- Prettier: 3.5+
- Babel: используйте flow-parser/babel-plugin; подробнее см. в нашем руководстве по Babel.
- ESLint: используйте flow-eslint; подробнее см. в нашем руководстве по ESLint.
См. также
-
Литеральные типы — литеральные типы, которые
as constвыводит для примитивных значений -
Кортежи — применение
as constк массивам приводит к созданию типов кортежей, доступных только для чтения -
Приведение типов — ключевое слово
asдля общих утверждений о типах (в отличие отas const) -
Обобщённые типы —
constпараметры типа для принудительного вывода типов const-выражений для аргументов функций -
Вариантность —
as constсоздаёт свойства, доступные только для чтения (ковариантные)
© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/types/const-expression