gpt4 book ai didi

javascript - Flow 不允许我将 `Array` 传递给 `Array`(子类型数组到父类(super class)型数组)

转载 作者:行者123 更新时间:2023-11-30 09:20:41 26 4
gpt4 key购买 nike

我有一个 Array<A> 类型的值(子类型数组)。 Flow 不允许我将它传递到期望 Array<A | B> 的地方(父类(super class)型数组),尽管它显然有效。

例如,我不能为 Array<'left' | 'right'> 类型的值赋值到类型为 Array<string> 的变量:

const directions: Array<'left' | 'right'> = ['right', 'left'];
const messages: Array<string> = directions; // error

引发此错误:

2: const messages: Array<string> = directions; // error
^ Cannot assign `directions` to `messages` because in array element: Either string [1] is incompatible with string literal `left` [2]. Or string [1] is incompatible with string literal `right` [3].
References:
2: const messages: Array<string> = directions; // error
^ [1]
1: const directions: Array<'left' | 'right'> = ['right', 'left'];
^ [2]
1: const directions: Array<'left' | 'right'> = ['right', 'left'];
^ [3]

Try Flow demo

同样,我不能传递 Array<ANode>到采用 Array<Node> 的函数, 即使 NodeANode | BNode :

type ANode = {type: 'a', value: string};
type BNode = {type: 'b', count: number};

type Node = ANode | BNode;

function getFirstNodeType(nodes: Array<Node>): string {
return nodes[0].type;
}

// works
const nodesSupertype: Array<Node> = [{type: 'a', value: 'foo'}];
getFirstNodeType(nodesSupertype);

// error
const nodesSubtype: Array<ANode> = [{type: 'a', value: 'foo'}];
getFirstNodeType(nodesSubtype); // error
16: getFirstNodeType(nodesSubtype); // error
^ Cannot call `getFirstNodeType` with `nodesSubtype` bound to `nodes` because property `value` is missing in `BNode` [1] but exists in `ANode` [2] in array element.
References:
6: function getFirstNodeType(nodes: Array<Node>): string {
^ [1]
15: const nodesSubtype: Array<ANode> = [{type: 'a', value: 'foo'}];
^ [2]

16: getFirstNodeType(nodesSubtype); // error
^ Cannot call `getFirstNodeType` with `nodesSubtype` bound to `nodes` because string literal `a` [1] is incompatible with string literal `b` [2] in property `type` of array element.
References:
1: type ANode = {type: 'a', value: string};
^ [1]
2: type BNode = {type: 'b', count: number};
^ [2]

Try Flow demo

最佳答案

Flow 会引发错误,因为它认为您可能会改变数组:

// given the definitions of `Node`, `ANode`, and `BNode` from the question’s second example

function getFirstNodeType(nodes: Array<Node>): string {
const bNode: BNode = {type: 'b', count: 0}
// Mutate the parameter `nodes`. Adding a `BNode` is valid according its type.
nodes.push(bNode);

return nodes[0].type;
}

const nodesSubtype: Array<ANode> = [{type: 'a', value: 'foo'}];
getFirstNodeType(nodesSubtype); // error

Try Flow demo

运行上面的代码后,nodesSubtype将包含 BNode即使它被声明为 ANode 的数组, 违反了它的类型。

有两种解决方案可以让 Flow 相信您不会改变数组。最清楚的是替换Array使用 Flow 实用程序类型 $ReadOnlyArray .

function getFirstNodeType(nodes: $ReadOnlyArray<Node>): string { // use $ReadOnlyArray
return nodes[0].type;
}

const nodesSubtype: Array<ANode> = [{type: 'a', value: 'foo'}];
getFirstNodeType(nodesSubtype); // no error

Try Flow demo

您只需在函数参数的类型中进行替换(例如 nodes ),但如果您愿意,可以使用 $ReadOnlyArray它适用于任何地方(例如 nodesSubtype )。

$ReadOnlyArray是最类型安全的解决方案,但您可能不希望必须更改所有现有函数才能使用它。在这种情况下,您的替代方法是通过 any 转换数组类型。 代替。是的,您可以从一开始就这样做,但至少现在您知道为什么进行此转换是安全的。您甚至可以发表评论来解释为什么存在此转换,这可能有助于您发现假设不再有效。

function getFirstNodeType(nodes: Array<Node>): string {
return nodes[0].type;
}

const nodesSubtype: Array<ANode> = [{type: 'a', value: 'foo'}];
// casting `Array<ANode>` to `Array<Node>` is okay because we know that `getFirstNodeType` won’t actually modify the array
getFirstNodeType(((nodesSubtype: any): Array<Node>));

Try Flow demo

如果您不关心记录问题,您可以省略注释并只转换为 any :

getFirstNodeType((nodesSubtype: any));

Try Flow demo

其他资源

关于javascript - Flow 不允许我将 `Array<A>` 传递给 `Array<A | B>`(子类型数组到父类(super class)型数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51933973/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com