2

流中的结构子类型化可能会导致信息丢失:

type O = {x: number, y: number};
type P = {x: number, y: number, z: number}

function f(o: O) {
    return o.x * 2, o.y * 2, o;
}

const p: P = {x: 2, y: 3, z: 100};
const r = f(p);

r.z // type error (property not found)

(这段代码很糟糕,因为它执行可见的突变。它仅用于说明目的。)

我已经读过行多态性是一个在不危及类型安全的情况下避免这种信息丢失的概念。

有没有办法通过亚型多态性实现相同的目标?

[编辑]

为了让更多的观众看到,我对这个有点吓人的术语做一个简短的解释:

  • Polymorphishm只是一个花哨的词,用于确定两种类型是否等价,即它使刚性类型系统更加灵活
  • 参数多态性(流中的泛型)表明两种类型总是等价的,因为类型根本不重要
  • 子类型多态性(流中的子类型)表明,如果您可以从中派生层次结构,则两种类型是等价的,即将子类型包含在其超类型下
  • 行多态性类似于子类型,但解决了信息丢失问题(但是从技术上讲,不再存在子类型关系,因此它不是子类型的一种形式)
  • 有界多态性表明两种类型仅在特定目的下是等价的,例如相等、顺序、映射等。
4

1 回答 1

1

对于我所阅读的有关 Flowtype 的内容,我很确定您的功能是问题所在。

如果您改为这样做:

function f<T: O>(o: T): T {
  o.x *= 2;
  o.y *= 2;
  return o;
}

r.z; // okay

这是因为有界多态性。现在在假设 T 是 O 的子类型的情况下检查身体类型。此外,在调用站点之间不会丢失任何信息。 在此处阅读更多相关信息。

另外,我之前没有听说过行多态,所以我去查了一下。在查找时,我已经阅读了几篇似乎表明行多态性不是子类型的东西。1、2、3。_ _ _ _

为了扩展这个答案并澄清为什么 OPs 功能不起作用,但我建议的功能可以正常工作。这也是一个很好的参考,但它是特定于 Java 的

通过具有以下功能:

function f(o: O) {
  return o.x * 2, o.y * 2, o;
}

该函数指定它正在显式查找 O 类型的对象,而不是 O 的对象或 O 的子类型。在 OPs 函数中,我们将参数 o 向下转换为类型 O,而不是使用泛型(这很糟糕)。处理这个问题的正确方法是利用泛型来指定它可以是 O 类型或 O 的子类型,可以按如下方式完成:

function f<T: O> (o: T): T {
  o.x *= 2;
  o.y *= 2;
  return o;
}

查看有关流如何处理泛型以及它如何与函数参数、对象等相关的文档。

相关部分是:

  • “泛型允许您在添加约束的同时保留更具体的类型。通过这种方式,泛型上的类型充当“边界”。链接

  • “泛型有时允许您将类似参数的类型传递给函数。这些被称为参数化泛型(或参数多态性)。” 关联

于 2017-09-14T20:42:07.123 回答