在@flow严格下,对于实用程序函数有哪些替代方法?

问题描述 投票:9回答:2

我有兴趣将我的Flow代码切换到strict类型检查,但我有一些低级实用程序函数,通常用于处理对象,例如:

// @flow strict

const hasKey = (o: Object): (string => boolean) =>
  Object.prototype.hasOwnProperty.bind(o);

const union = (os: Array<Object>): Object =>
  os.reduceRight((acc, o) => ({ ...acc, ...o }), {});

由于在严格模式下不允许使用Object类型,因此如何为明确应该在任何通用Object上操作的函数声明类型?

javascript node.js flowtype strict
2个回答
4
投票

在这种情况下,你实际上会从更严格的打字中受益匪浅。通过使用Object,您实际上是为所有通过这些函数的数据关闭打字系统,直到可以在其他地方显式重新键入它们。这意味着您目前正在丢失大量不需要的输入信息。

这是一个关于泛型的教科书案例,记录了here

// @flow strict
const hasKey = <T: {}>(o: T): (string => boolean) =>
  Object.prototype.hasOwnProperty.bind(o);

const union = <T: {}>(objects: Array<T>): T =>
  objects.reduce((acc, o) => ({ ...acc, ...o }), ({}: $Shape<T>));

上面最重要的部分是: {}中的<T: {}>。这些是类型边界。如果泛型是一种说法,“允许用户传递他们想要的任何类型,并将该类型存储在变量中以便以后可以引用它”,那么类型边界是一种说“允许用户传递他们想要的任何类型,只要该类型是X类型的成员。“

由于width subtyping的工作方式,{}是最通用的对象类型。实际上,所有对象都是{}的子类型。所以<T: {}>基本上意味着,“T应该是任何类型的对象。”

请注意,这与<T: Object>非常不同,const o: Object = {}; console.log(o.some.member.that.doesnt.exist); // no error at compile time, // but obvious error at runtime 基本上意味着“T是一个对象,从现在起我还没有检查任何其他内容。”这意味着我们可以做以下事情:

const o: {} = {};
console.log(o.member); // Error, we don't know about this member property!

不同于:

{}

因此,通过告诉flow该参数是T的子类型,我们告诉它它具有对象的基本API。它有属性,它可以是休息和传播,它可以是字符串索引等,但没有别的。此外,通过将数据类型存储为通用function union <T>(os: Array<T>): T { ... } 并返回该类型,我们维护参数的类型信息。这意味着无论我们作为一个参数传递什么,我们都会从另一方获得相同类型的东西(而不是一个黑盒子的神秘)。


0
投票

也许您可以使用流程泛型编写函数。例如。,

https://flow.org/en/docs/types/generics/

文档:qazxswpoi

© www.soinside.com 2019 - 2024. All rights reserved.