2017-01-16 3 views
1

Try flow link.Возможно ли уточнить ограниченный полиморфный тип?

Вот простой пример ограниченного полиморфизма, который не работает так, как я ожидаю, что это:

// @flow 

function thisBreaks<T: 'a' | 'b'>(x: T): T { 
    if (x === 'a') { 
    return 'a' 
    } else { 
    return 'b' 
    } 
} 

function thisWorks<T: 'a' | 'b'>(x: T): T { 
    return x 
} 

const a = 'a' 
const aPrime: 'a' = thisWorks(a) 
const b = 'b' 
const bPrime: 'b' = thisWorks(b) 

5:  return 'a'    
      ^string. This type is incompatible with the expected return type of 
3: function thisBreaks<T: 'a' | 'b'>(x: T): T { 
^some incompatible instantiation of `T` 

7:  return 'b'    
      ^string. This type is incompatible with the expected return type of 
3: function thisBreaks<T: 'a' | 'b'>(x: T): T { 
^some incompatible instantiation of `T` 

я ожидал бы первый пример для работы, так как, например, x === 'a' чек может усовершенствовать T до 'a', правильно?

+0

Хотя это невозможно, вы можете выполнить то, что хотите делать с функцией пересечения. Я создал рабочий тип для вашей функции: [Попробуйте ссылку потока] (https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVBjOA7AzgFzCjjgC4wAKCgD3IHIBDOgSjAF4A+MRl1MfgQIBklGvQBGLdlzqTmqNqOrSwytuu5MwAfk10wEluQbYAnvMw4CYcQwBO9LYuJwKPeVjyFbAL0PsiEjc5Sy8iBgBLGFxHfWcg2V4gA) – Andy

ответ

2

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

function test<T: number | string>(x: T): T { 
    if (typeof x === 'number') { 
    return 1; 
    } else { 
    return 'b' 
    } 
} 

test((5: 5)); 

Функция должна возвращать значение типа 5, но возвращает 1 вместо этого.

Итак, что происходит? У нас есть неизвестный тип T, и мы знаем, что T <: string | number (T - подтип string | number). После уточнения x мы знаем, что T является подтипом number. Это не означает, что Tявляетсяnumber. Это может быть 5, как в примере, или 1 | 2 | 3. Знать, что T является подтипом number, недостаточно для создания значения T. Для этого нам нужно знать нижнюю границу T, но нет способа узнать ее.

Последний вопрос: почему вы, например, по-видимому безопасны? Это просто: если T <: 'a', то это может быть только 'a' (или empty, но это не имеет значения). Других подтипов 'a' нет. Итак, теоретически Flow мог поддержать это, но его не очень практично: если вы знаете, что x - 'a', то вы можете просто вернуть x

+0

Спасибо! Да, я видел ваш ответ на https://github.com/facebook/flow/issues/3219. Я определенно не думал о последствиях таких конкретных типов. –

+0

Актуальная проблема, которая мотивировала мой вопрос, находится здесь: http://stackoverflow.com/questions/41496896/typing-a-camel-caser-in-flow-variance-issues. Правильно ли я имею в виду, что просто невозможно отличить верблюд от точного типа потока? –

+0

Справа. Единственный способ произвести что-то типа T - взять что-то, что уже имеет тип T. – vkurchatkin

 Смежные вопросы

  • Нет связанных вопросов^_^