класс реализует интерфейс, но поток говорит, что этот тип несовместим

Я пробовал это с потоком 0.57.3 и 0.59.0

flowtype.org/try code

Я определяю интерфейс для классов, которые содержат вещи:

interface IHolder<SomeType>  {
    give(): SomeType;
}

Теперь я определяю класс, который реализует этот интерфейс:

class AHolderOfNumber implements IHolder<number> {
    give(): number {
        return 42;
    }
}

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

type FunctionThatUsesAHolder<SomeType> = (x: IHolder<SomeType>)=>void;

Сейчас я определяю функцию, которая использует AHolderOfNumber:

function foo(x : AHolderOfNumber) {} // do nothing, this is just an example

Пока все хорошо, все проверено.

В моей книге, поскольку класс AHolderOfNumber реализует IHolder<number>, следует, что функция foo имеет тип FunctionThatUsesAHolder<number>.

Тем не менее, строка ниже не проходит проверку типов:

(foo : FunctionThatUsesAHolder<number>)

Поток жалуется на:

Error: src/example.js:69
 69: (foo : FunctionThatUsesAHolder<number>)
      ^^^^ function. This type is incompatible with
 69: (foo : FunctionThatUsesAHolder<number>)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type
  This parameter is incompatible:
     57: type FunctionThatUsesAHolder<SomeType> = (x: IHolder<SomeType>)=>void;
                                                      ^^^^^^^^^^^^^^^^^ IHolder. This type is incompatible with
     65: function foo(x : AHolderOfNumber) {
                          ^^^^^^^^^^^^^^^ AHolderOfNumber


Found 1 error

Что дает?


person Marcus Junius Brutus    schedule 27.11.2017    source источник
comment
Как правило, функциональный пример на flowtype.org/try очень помогает ответить на вопросы о Flow, так как люди могут поиграть с кодом. .   -  person loganfsmyth    schedule 28.11.2017
comment
@loganfsmyth не знал о flow.org/try. Это потрясающе. Просто добавил ссылку в начало поста.   -  person Marcus Junius Brutus    schedule 28.11.2017


Ответы (1)


Так собственно вопрос: почему (AHolderOfNumber) => void не совместим с (IHolder<number>) => void?

Предположим, что у AHolderOfNumber есть дополнительный метод bar и функция foo выглядит примерно так:

class AHolderOfNumber implements IHolder<number> {
    give(): number {
        return 42;
    }

    bar() {
    }
}

function foo(x : AHolderOfNumber) {
    x.bar()
}

Если поток позволит вам преобразовать функцию foo в функцию, которая требует менее конкретного параметра, вы можете получить ошибку времени выполнения, если передадите реализацию IHolder<number> без метода bar:

class BHolderOfNumber implements IHolder<number> {
    give(): number {
        return 11;
    }
}

const requiresLessSpecific = (foo : (IHolder<number>)=>void);

let bHolder = new BHolderOfNumber();
requiresLessSpecific(bHolder); //runtime error

Подробнее о вариации типов здесь

person Aleksey L.    schedule 28.11.2017