Я читал PR контекстного API для React Эндрю Кларка и увидел следующий код:

((frame: any): FrameDev).debugElementStack = [];

Синтаксис был мне незнаком, когда я впервые прочитал его, к счастью, там был комментарий, объясняющий, как это работает, но я подумал, что это требует более подробного объяснения.

Поскольку Flow основан на JavaScript, типы, которые вы можете создавать с его помощью, более гибкие, чем типы, которые вы создаете в языках, в которых типы встроены в спецификацию.

В документах Flow кратко упоминаются небезопасные приведения типов:

Приведя значение к любому, вы можете затем привести его к чему угодно.

Это небезопасно и не рекомендуется. Но иногда это полезно, когда вы делаете что-то со значением, которое очень сложно или невозможно ввести, и хотите убедиться, что результат имеет желаемый тип.

Причина, по которой этот метод не описан более подробно, заключается в том, что это взлом. Однако этот хак уникален для систем типов, таких как Flow, и позволяет сбалансировать свободу свободных типов с безопасностью статических типов, поэтому стоит разобраться в этом подробнее.

Рассмотрим следующий код:

// @flow
const toString = (num: number) => {
  return num.toString();
};
const add = (a: number, b: number) => {
  return a + b;
};
const a = toString(1);
const b = toString(2);
add(a, b);

Это даст вам следующую ошибку в Flow:

string This type is incompatible with the expected param type of number

В языке со статической типизацией нам пришлось бы каждый раз проверять тип переменной, а затем преобразовывать ее. Это пример того, как небезопасное приведение типов позволяет нам обменять часть безопасности статического типа на свободу свободного типа:

const a = (toString(1): any);
const b = (toString(2): any);
add(a, b);

Это сбрасывает тип a и b на any, который в этом случае может перейти в number. К сожалению, этот сброс также приводит к ошибке следующего кода:

const a = (toString(1): any);
const b = ("string": any);
add(a, b);

Потому что "string" + 1 — это допустимый JavaScript, который оценивает to"string1" из-за приведения типов, что является основной причиной существования Flow, поэтому это хак. Чтобы теперь Flow выдал ошибку, вам нужно сделать что-то конкретное для этой переменной:

const add = (a: number, b: number) => {
  a = a.toFixed(a); // format a to two decimals 
  return a + b;
};
const a = (toString(1): any);
const b = ("string": any);
add(a, b);

В этом случае Flow выдаст ошибку a = a.toFixed(a) с:

string This type is incompatible with the expected param type of number

Вам следует избегать этой техники, когда это возможно, но, поняв, как она работает, вы сможете применять ее выборочно и сэкономить много времени.