Подтвердить что ты не робот

Как заставить поток принудительно использовать значение для другого типа?

Можно ли принудительно применить переменную в Flow?

type StringOrNumber = string | number
const foo:StringOrNumber = 'hello'

// I look for something like `const bar:string = (string) foo`
const bar:string = foo // fails
const bar:string = (foo: string) // also fails
4b9b3361

Ответ 1

Flow не выполняет непосредственное кастинг от одного типа к другому, но вы можете сделать что-то вроде

const bar: string = (foo: any);

поэтому вы отбрасываете foo в any, потому что any принимает любой тип значения в качестве ввода. Тогда, поскольку тип any также позволяет вам читать все возможные типы, вы можете назначить значение any bar, потому что any также является string.

Ответ 2

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

Установив тип foo на string | number, мы сказали Flow, что это значение может быть либо строкой, либо числом. Затем мы помещаем в него строку, но Flow не отбрасывает наше прямое утверждение о ее типе из-за этого даже в ситуациях (например, этот), где он не может измениться позже.

Чтобы назначить его переменной string -typed, Flow должен знать, что даже если это могло быть либо string, либо number, к тому времени, когда мы выполняем задание, мы уверены, что он может только a string.

Этот процесс сокращения возможных параметров называется уточнением типа.

Уточнения типов

Чтобы уточнить тип, нам нужно доказать, что он должен быть типом, который мы говорим, каким-то образом понимает Flow.

В исходном примере вы можете сделать это, используя typeof:

type StringOrNumber = string | number
const foo: StringOrNumber = 'hello'

const bar: string
if (typeof foo === "string") {
  // Flow now knows that foo must be a string, and allows this.
  bar = foo
}

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

Комментарии подавления

Иногда нет способа выразить безопасность уточнения Flow. Мы можем заставить Flow принять выражение с помощью комментария , который будет подавлять сообщение об ошибке, которое в противном случае сообщалось бы. Замечание о подавлении по умолчанию - $FlowFixMe, но его можно настроить на разные комментарии или комментарии.

Поток сообщит об ошибке во второй строке этого сообщения, сообщив, что unionValue может иметь тип 'number':

const unionValue: StringOrNumber = 'seven'
const stringValue: string = unionValue

Однако, используя комментарий подавления, это пропускает Flow:

const unionValue: StringOrNumber = 'seven'
// $FlowFixMe: We can plainly see this is a string!
const stringValue: string = unionValue

Одна из полезных особенностей комментариев подавления заключается в том, что комментарий о подавлении без следующей ошибки для подавления считается ошибкой. Если мы изменим тип в примере:

const unionValue: string = 'seven'
// $FlowFixMe: Even though this is a string, suppress it
const stringValue: string = unionValue

Теперь Flow сообщит об ошибке "Неиспользуемое подавление", предупредив нас. Это особенно полезно, когда Flow должен иметь возможность распознавать уточнение, но не может - с помощью комментария подавления мы предупреждаем об удалении комментария (и получаем дополнительную безопасность типа), если будущая версия Flow распознает код как типобезопасный.

Монолитный сквозной любой

Если вы действительно не можете выразить это так, чтобы продемонстрировать свою безопасность для потока, и вы не можете (или не будете) использовать комментарий подавления, вы можете применить любой тип к any и any для любого типа:

const unionValue: StringOrNumber = 'seven'
// Flow will be okay with this:
const stringValue: string = (unionValue: any)

Извлекая значение any, мы просим Flow забыть все, что он знает о типе значения, и предположить, что все, что мы делаем с ним, должно быть правильным. Если позже мы введем его в типизированную переменную, Flow предположим, что это должно быть правильно.

Предостережения

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

const notAString: {key: string, key2: number} = {key: 'value', key2: 123}
// This isn't right, but Flow won't complain:
const stringValue: string = (notAString: any)

В этом примере stringValue удерживает object от notAString, но Flow уверен, что это строка.

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

Ответ 3

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

Чтобы удовлетворить проверки типов, я только что представил этот общий защитник и назвал его cast (который, конечно же, не делает его отличным), потому что в противном случае мой код настолько раздулся.

Разумеется, стоимость стоит в производительности (что очень важно при написании игр, но я думаю, что большинство случаев использования выигрывают больше от типов охранников, чем миллисекунды за итерацию).

const cast = (type : any, target : any) => {
    if (!(target instanceof type)) {
        throw new Error(`${target} is not a ${type}`);
    }
    return target;
}

Обычаи:

const fooLayer = cast(HTMLCanvasElement, document.getElementById("foo-layer"));
window.addEventListener("click", (ev : Event) =>
  console.log(cast(MouseEvent, ev).clientX - cast(HTMLElement, ev.target).offsetLeft,
    cast(MouseEvent, ev).clientY - cast(HTMLElement, ev.target).offsetTop));