типы потоков с постоянными строками и зависимые типы

Скажем, у меня есть следующая постоянная строка:

export default const FOO = 'FOO'

Скажем, я импортирую это в аннотированный файл потока следующим образом:

import FOO from '../consts/Foo'

Затем у меня есть функция:

const example = (foo : string) : {| type: FOO, foo: string |} => {
  return {type: FOO, foo: foo}
}

Это не проверяет тип с:

  6: const example = (foo : string) : {| type: FOO, foo: string |}=> {
                                                         ^^^^^^^^^^^^^^ string. Ineligible value used in/as type annotation (did you forget 'typeof'?)
  6: const example = (foo : string) : {| type: FOO, foo: string |}=> {
                                                         ^^^^^^^^^^^^^^ FOO

Итак, мои вопросы:

1) можно ли использовать константы в типах потока, как я могу воспроизвести это поведение?

2) Можно ли делать зависимые типы в потоке? так, например, могу ли я закодировать через типы, что возвращаемая строка должна быть той же строкой, которая передается в функцию example?

РЕДАКТИРОВАТЬ: Пояснение к части 2: можно ли каким-то образом указать, что параметр foo, переданный в функцию example, на самом деле является той же строкой, что и строка в ключе foo в возвращаемом объекте? Или утверждать, что вход и выход имеют одинаковую длину (например, функция шифрования сдвига). Или, скажем, содержат перестановку одних и тех же символов? (для перетасовки).

https://en.wikipedia.org/wiki/Dependent_type


person Abraham P    schedule 13.02.2017    source источник
comment
Если вы хотите, чтобы FOO имел тип 'FOO', вам нужно объявить его, иначе это просто строка. Для объектов вы должны сделать type: typeof FOO, как говорит ошибка. Я не совсем уверен, о чем вы спрашиваете в своем 2) пункте. Тогда вы получите объект с двумя свойствами с одинаковым строковым значением.   -  person loganfsmyth    schedule 13.02.2017


Ответы (2)


Вместо того, чтобы объявлять FOO как const, объявите его как непересекающееся объединение только с одной ветвью:

type FOO = "FOO"

Затем ваш код можно обновить следующим образом:

const example = (foo : string) : {| type: FOO, foo: string |} => {
  return {type: "FOO", foo: foo}
}

Если вы используете любое значение, кроме точного строкового литерала "FOO", где требуется FOO, то это ошибка компиляции.

Если вы предпочитаете сохранить свою константу, вам нужно будет назвать тип по-другому, так как они будут конфликтовать. Итак, вы можете сделать:

const FOO = "FOO"
type FooType = "FOO";

const example = (foo : string) : {| type: FooType, foo: string |} => {
  return {type: FOO, foo: foo}
}

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

person Peter Hall    schedule 13.02.2017
comment
для стандартного шаблона действий Flux, определяющего типы действий в виде строк, чтобы убрать некоторые кавычки из кода, это очень интересный шаблон. Таким образом, и поправьте меня, если я ошибаюсь, я могу определить метатип ValidResponses = FOO | BAR ; и убедиться, что вызов функции API возвращает правильный ответ, а не только правильный тип данных. - person ermik; 23.01.2018

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

export default const FOO:'FOO' = 'FOO'

то в функции вы можете использовать как

const example = (foo : string) : {| type: typeof FOO, foo: string |} => {
return {type: FOO, foo: foo}
}

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

person v3n0msnake    schedule 30.09.2020