【问题标题】:How to define a generic type in flow that have all the fields optional of specified type如何在流中定义具有指定类型的所有可选字段的泛型类型
【发布时间】:2018-07-07 18:18:30
【问题描述】:

我们可以很容易地在 typescript 中定义一个泛型类型,它可以让所有字段对于传递的泛型类型都是可选的。这种类型的查询在类型定义中非常有用,可以定义 mongo 查询的结果,因为我们可能不需要获取所有字段,并且可以通过可选的类型规范进行验证。

https://www.typescriptlang.org/docs/handbook/advanced-types.html

interface Person {
    name: string;
    age: number;
}

type Partial<T> = {
    [P in keyof T]?: T[P];
}

const p : Partial<Person> = {
    name:"A"
}

如何使用 Flow 定义相同的事物。我们可以使用 $Keys。但在定义另一种类型时无法获得它的类型,就像我们在类型脚本中所做的那样。 -- [P in keyof T]?: T[P];我们无法在 Flow 中获得 P。 https://flow.org/en/docs/types/utilities/#toc-keys

type Person = {
    name: string,
    age: number;    
}

type Partial<T> = {
    [$Keys<T>] : 1;  // doubt here how to get type of prop comes in left
}

const p : Partial<Person> = {
    name:"A"
}

实际我们正在尝试为 Query 编写类型规范。我们也不能为未指定的键提供 null 或 undefined。

type Department = {
    _id : string,
    name : string,
    type : string
}

type Person = {
    _id : string,
    name : string,
    age : number,
    department : Department
}

type Query <T> = {
    [P in keyOf T ]?: 1 | Query<T[P]> 
}

type Document<T> = {
    [P in keyOf T ]?: T[P] | Document<T[P]>     
}

const personDepartments  : Query<Person> = {
    name:1, department :{name:1}
}

这个查询将返回一些结果如下

{_id:"1",name:"abc",department:{name:"xyz"}}

可以是文档类型

const a : Document<Person> = {_id:"1",name:"abc",department:{name:"xyz"}}

所以我们可以编写如下函数

function getResult<T>(query:Query<T>) : Document<t> {
    // code here to query and get result
}

在 TypeScript 中非常简单。所以我想Flow中也应该有解决方法。

【问题讨论】:

  • 你好团队:有可能吗?
  • TL;DR - 没有答案。但只是好奇,所有字段都是可选的类型有什么意义?无论如何,在使用它之前,您都需要对它们进行空检查。这里唯一的限制是添加不在Person 类型中的字段,但这是您首先需要的吗?我们的方法是我们总是假设 DB 返回mixed,因为应用程序。无法控制 DB,因此我们永远无法 100% 确定来自 DB 的内容。在我们得到一个mixed-type 结果后,我们应用一个映射器来确保到达的数据是准确的预期类型。如果不是“意外数据”,则触发处理程序。
  • 谢谢维克多。当我们定义 mongo 查询并在视图上显示结果时,我们实际上有一个用例。我们必须在视图(ui 端)上显示更少的列。所以我们需要创建一个可以期望更少列的类型定义。而且我们不能在主类型中使每一列都是可选的,因为在保存文档时,必须具有强制列的值。但我认为它不应该是流式的,因为它起源于类型脚本,并且它的大部分语法与打字稿相似。所以应该有一种我们没有找到的流程方式可能是由于没有记录。
  • “所以我们需要创建一个可以期望更少列的类型定义” - 所以,您正在尝试创建另一种类型(即 PersonForView),其中所有字段都是可选的,对吧?如果是,那么我的问题仍然存在——为什么你需要一个所有字段都是可选的类型?视图仍然必须对所有字段进行空检查。你需要这种类型吗? “它起源于类型脚本” - 我目前没有证据,但我怀疑 Flow 起源于 TS - 它们非常不同,它们使用完全不同的类型推理算法并用不同的语言编写(分别为 OCaml 和 TS )。
  • 感谢 Viktor 的澄清。为视图定义一个类型似乎是重复的工作并且容易出错,因为没有办法验证它是否是主类型。

标签: typescript flowtype


【解决方案1】:

您可以使用$Shape 实用程序:

复制所提供类型的形状,但将每个字段标记为可选

type Foo = {
  A: string,
  B: number,
  C: string
};

const t: $Shape<Foo> = {
  A: 'a'
};

另一种方法是“传播”类型(抱歉,除了changelog,找不到任何关于它的文档):

type Foo = {
  A: string,
  B: number,
  C: string
};

type Partial<T> = { ...T };

const t: Partial<Foo> = {
  A: 'a'
};

现在它确实是部分的,您可以跳过键。

【讨论】:

  • 谢谢阿列克西。我们会尝试的。
【解决方案2】:

您可以接近$ObjMap&lt;T, F&gt;,它将函数类型F 应用于T 的每个属性。

type Foo = {
  A: string,
  B: number,
  C: string
};

function makeOptional<T>(t: T): ?T {
  return t;
}

type PartialFoo = $ObjMap<Foo, typeof makeOptional>;

const t: PartialFoo = {
  A: 'a',
  B: null,
  C: undefined
};

但是,在这种情况下,您仍然不能跳过键,但可以将 null 或 undefined 添加到它们的值中。

【讨论】:

  • 感谢 EyasSH。实际我们正在尝试为 Query 编写类型规范。我们也不能为未指定的键提供 null 或 undefined 。正如我编辑我的问题以解释我们想要什么。直接在 TypeScript 中是可能的
猜你喜欢
  • 2019-10-02
  • 2020-01-07
  • 1970-01-01
  • 2019-07-21
  • 2017-10-27
  • 1970-01-01
  • 2016-04-28
  • 2012-03-29
  • 2021-01-06
相关资源
最近更新 更多