如何构建一个不相交的联合包装器以便改进工作?

时间:2017-01-02 22:15:41

标签: flowtype

On the Flowtype "Try" site

// @flow

type One = {type: "One"};
type Two = {type: "Two"};
type Node = One | Two;


class Foo<N: Node> {
  node: N;

  constructor(n: N) {
    this.node = n;
  }
}

const fooNode: Foo<Node> = new Foo({type: "One"});
if (fooNode.node.type === "One") {
  const fooOne: Foo<One> = fooNode;
}

if类型检查不足以细化类型,如果我理解正确的话,因为类型不能保证是恒定的。

由于我想避免这是一个X / Y问题的可能性,我现在玩的用例是使用.find方法从给定节点进行搜索,该方法将返回精炼类型,例如使用

  parent(): Foo<N> | null {
    // ...
    return null;
  }

  find<U: Node>(callback: (foo: Foo<N>) => Foo<U> | null): Foo<U> | null {
    let p = this;
    do {
      const result = callback(p);
      if (result) return result;

      p = p.parent();
    } while (p);

    return null;
  }

const f: Foo<Node> = new Foo({type: "One"});

const result: Foo<Two>|null = f.find((p) => p.node.type === "Two" ? p : null);

这将允许我在搜索时返回精炼类型。

2 个答案:

答案 0 :(得分:2)

问题在于此行上的类型注释:

const fooNode: Foo<Node> = new Foo({type: "One"});

明确使用Foo<Node>,您可以防止细化发生。您可以使用Foo<*>使推理正常工作。

以下是一个例子: https://flowtype.org/try/#0PTAEAEDMBsHsHcBQiAuBPADgU1AeQHY4C8oA3qOtgFygBEBWtoAvgNyqY4Aq8soJ5Slhq0esJmw7ZQAOVgATYnkKgAPqDHtEAY2gBDAM4HQAMViwAPDJpzFAPjKJQofAuGytz7bHwGUAJwBXbRRYfwAKfBsASkdnZxQACwBLAwA6V0V+F3ZnZkR85G9fFFBIc1t3M0sAKgcSQnhTc3DSIREGWmZo9nDy2EqaaosGOx7EPoq3IfMLMTHWUBBQLH9-MKA

答案 1 :(得分:2)

有两个问题。 Foo是不变的,因此您永远无法对其进行优化:它除了自身之外没有任何已知的子类型。

另一方面,即使Foo是协变的,它也不会起作用。你根本无法改进泛型类。

唯一可行的选择是再次打开包装,精炼和包装。