Flow中的可组合合同和正合同

时间:2019-04-26 13:30:13

标签: javascript flowtype

我遇到了Flow问题,其中给定的已实现type限制了我的对象API,要求我仅使用在type上声明的属性,而不是要求我声明所有type的属性。

我是Flow的新手,所以我可能正在犯一些基本的错误。无论如何,我已经声明了以下type

type Unit = {
  of(value: any): Monad,
};

我要在这里说的是:根据Unit实现的所有对象都必须具有一个#of方法,该方法可以接收给定的value并返回一个{{1} }类型的值。

当我在工厂实施时,没问题:

Monad

但是当我尝试致电const Maybe: Unit = { isMaybe: (obj): boolean => { ... }, of: (value): Monad => { ... }, }; 时,出现此错误(在linter上):

#isMaybe

现在,我尝试在flow(0|2), isMaybe (Cannot call: `Maybe.isMaybe` because property `isMaybe` is missing in `Unit` [1].) 上声明#isMaybe,并且错误按预期消失了。问题是,Unit应该是一种自由接口,用于检查其实现是否具有Unit属性,而不是仅 Unit属性。

我无法重构-至少我不知道-从UnitUnit的{​​{1}},因为我是通过type关系构成它们的: / p>

interface

是否有任何方法可以使Flow产生积极且可组合的合同?

2 个答案:

答案 0 :(得分:1)

我对肯定和可组合性也不太熟悉,但是我认为interface可以帮助解决问题。您可以轻松扩展interface并将一个变量声明为1。查看下面的示例,以了解如何使用和扩展接口。请注意,在这种特殊情况下无需遍历类。

type Monad = any;

interface Unit {
  of(value: any): Monad;
}

const unit: Unit = {
  of(value: any): Monad {
    return value;
  }
}

const notUnit: Unit = {};

const alsoNotUnit: Unit = {
  isMaybe(value: any): boolean {
    return false;
  }
}

interface Maybe extends Unit {
  isMaybe(value: any): boolean;
}

const maybe: Maybe = {
  isMaybe(value: any): boolean {
    return true;
  },
  of(value: any): Monad {
    return value;
  }
}

const notMaybe: Maybe = {
  isMaybe(value: any): boolean {
    return true;
  }
};

const alsoNotMaybe: Maybe = {
  of(value: any): Monad {
    return value;
  }
}

Ttry Flow

警告一下,因为我看到您使用了&交集类型运算符-交集类型当前在Flow中是断开的并且不一致。我建议暂时不要使用它们。它们的大多数行为都可以通过其他更正确的方法来完成,例如散布运算符或extends

答案 1 :(得分:0)

我对您的意思不是很熟悉,“有什么方法可以使Flow产生积极且可组合的合同吗?” (我假设这是来自另一种语言吗?),并且我没有按照您描述的方式使用流程;这是将函数定义定义为类型的一部分,但我希望这里的方法会对您有所帮助。

我在这里要做的第一件事是为MaybeUnit

创建第二种类型
export type MaybeUnit = Unit &{
  isMaybe: (obj): boolean
};

但是,我再一次不熟悉该函数是否属于该类型。每当我想要一个函数时,我都会定义一个类(可能带有interface)而不是类型。这可能会使您的实现看起来像这样:

interface IUnit {
  of(value: any): Monad;
}

class Unit implements IUnit {
  of(value): Monad { 
    return new Monad();
  }
}

interface IMaybeUnit extends IUnit {
  isMaybe({}): boolean;
}

class MaybeUnit extends Unit implements IMaybeUnit {
  isMaybe({}): boolean { 
    return true;
  }
}

希望这种方法可以解决您的问题。

更新:添加了我有时对管理器类所做的一个示例。这是一种非常冗长的方法,并且仅在某些情况下适用。当使用流运行时以便在执行时而不是在构建时测试类型时,它也更加有用。

class UnitManager {

  static UnitTypes:Map<string, IUnit>;

  static RegisterUnitType( key:string, klass:Class ) {
    UnitManager.UnitTypes.set( key, klass );
  }

  static CreateUnit( unit:IUnit ):Unit {
    // test data to determine type
    let type:string = UnitManager.GetUnitType( unit );
    let klass:Class = UnitManager.UnitTypes.get( type );
    return new klass( unit );
  }

  static GetUnitType( unit:IUnit ):IUnit {
    // Magic. Your logic to determine the type based on the data provided. if you use flow-runtime, you can use instanceOf, otherwise I think you need to test if the keys exist in the data, or something.
  }
}

起初我没有包括它,因为它不是很干净,并且经常会成为反模式。在某些情况下这很有用,我发现自己主要是为了避免循环依赖。

有时我会拥有它,以便每个类的构造函数根据其类中的静态“名称”常量向管理器注册自己。