在Flow中注释对包含可选参数的联合类型进行操作的函数

时间:2016-10-07 02:38:57

标签: javascript flowtype

我为糟糕的头衔道歉,我不知道如何更好地描述这个:)

我在基于具有自动递增ID的IndexedDB数据库的应用程序中使用Flow。所以基本上,我创建了一些对象(没有id属性),将它们写入数据库(此时它们被IndexedDB赋予id属性),然后将它们读回(任何对象)从DB读取保证具有数字id属性。)

我有一些操作这些对象的函数。有时它们只对具有ID的对象进行操作,有时它们只对没有ID的对象进行操作,有时它们同时对两者进行操作。这是最棘手的后一种情况。这是一次尝试,在写入数据库之前和之后使用两种不同类型的对象(因此,分别没有和使用id属性):

/* @flow */

type BeforeDb = {prop: string};
type AfterDb = BeforeDb & {id: number};

var beforeDb: BeforeDb = {prop: 'hi'};
var afterDb: AfterDb  = {id: 1, prop: 'hi'};

function a(obj: BeforeDb | AfterDb): BeforeDb | AfterDb {
  if (typeof obj.id === 'number') {
    console.log(obj.id * 2);
  }
  return obj;
}

function b(obj: AfterDb) {}

var x = a(afterDb);
b(x);

(demo link)

这会在最后一行产生错误,因为它不知道x属于AfterDb类型,而且我不确定如何正确传达这些信息。

另一个想法是使用bounded polymorphisms,但我不相信这可以创建类似我上面的a函数的东西,因为它无法处理id有时候的事实未定义。就像我想做这样的事情:

function a<T: {id?: number}>(obj: T): T {
  if (typeof obj.id === 'number') {
    console.log(obj.id * 2);
  }
  return obj;
}

(demo link)

但这不起作用。如果我为id分配了一个虚拟值,那么它总是数字的(比如-1而不是undefined)那么这就行了,但是我必须非常小心地记住要删除id在第一次写入数据库之前,可以自动生成真实id,这将非常难看。

在那之后,我几乎是出于好主意。我要做的一件事就是只使用一种类型,例如:

type Obj = {id?: number, prop: string};

然后显式检查每个使用id属性的函数中是否存在id属性。但这很烦人,因为我有一堆只用IndexedDB的输出调用的函数,所以我已经知道id保证在那里。我只是不知道怎么告诉Flow。

有什么想法吗?

1 个答案:

答案 0 :(得分:5)

function a<T: BeforeDb | AfterDb>(obj: T): T {
  if (typeof obj.id === 'number') {
    console.log(obj.id * 2);
  }
  return obj;
}