对Flow中对包含可选参数的并集类型进行操作的函数进行注释

Annotating functions in Flow that operate on union types containing optional parameters

本文关键字:操作 注释 函数 类型 Flow 包含可 参数      更新时间:2023-09-26

我为这个糟糕的标题道歉,我不知道如何更好地描述它:(

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

我有一些对这些对象进行操作的函数。有时他们只对有ID的对象进行操作,有时他们只在没有ID的对象上进行操作,有时候他们同时对两者进行操作。后一种情况最为棘手。这里有一个尝试,在对象写入DB之前和之后使用两种不同的类型(因此,分别不使用和使用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);

(演示链接(

这在最后一行产生了一个错误,因为它不知道x的类型是AfterDb,我也不知道如何适当地传达该信息。

另一个想法是使用有界多态性,但我不相信这能创建类似于我上面的a函数的东西,因为它不能处理id有时是不定义的事实。就像我想做这样的事情:

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

(演示链接(

但这行不通。如果我给id分配了一个伪值,所以它总是数字的(比如-1,而不是未定义的(,那么这会起作用,但我必须非常小心,记住在第一次写入数据库之前删除id,这样才能自动生成真正的id,这会非常难看。

在那之后,我几乎没有什么好主意了。我要做的一件事就是只使用一种类型,比如:

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

然后显式地检查在使用CCD_ 13属性的每个函数中是否存在CCD_。但这很烦人,因为我有很多函数只使用IndexedDB的输出进行调用,所以我已经知道id一定会存在。我只是不知道该怎么告诉Flow。

有什么想法吗?

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