一个不相交的联合包装器应该如何构造才能使细化工作?
How should a disjoint union wrapper be structured for refinement to work?
// @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
方法从给定节点搜索 .find
=27=] 精化类型,例如使用
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);
这将允许我在搜索时 return 精炼的类型。
问题出在这一行的类型注释上:
const fooNode: Foo<Node> = new Foo({type: "One"});
通过显式使用 Foo<Node>
,您可以防止进行优化。您可以使用 Foo<*>
使推理正常工作。
有两个问题。 Foo
是不变的,因此您永远无法细化它:除了自身之外,它没有任何已知的子类型。
另一方面,即使 Foo
是协变的,它也行不通。您根本无法优化通用 class.
唯一可行的选择是展开、精炼并再次包裹。
// @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
方法从给定节点搜索 .find
=27=] 精化类型,例如使用
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);
这将允许我在搜索时 return 精炼的类型。
问题出在这一行的类型注释上:
const fooNode: Foo<Node> = new Foo({type: "One"});
通过显式使用 Foo<Node>
,您可以防止进行优化。您可以使用 Foo<*>
使推理正常工作。
有两个问题。 Foo
是不变的,因此您永远无法细化它:除了自身之外,它没有任何已知的子类型。
另一方面,即使 Foo
是协变的,它也行不通。您根本无法优化通用 class.
唯一可行的选择是展开、精炼并再次包裹。