问题描述
我的代码如下:
export function testGraph({ id = 0,name = "test",nodes = [] }): Graph {
if (nodes.length === 0) {
const dummyNode = testNode({});
return new Graph(id,name,[dummyNode]);
}
return new Graph(id,nodes);
}
export function testDatabase({ id = 0,graphs = [] }): Database {
if (graphs.length === 0) {
const dummyGraph = testGraph({ nodes: new Array(new Node(0)) });
return new Database(id,[dummyGraph]);
}
return new Database(id,graphs);
}
但这给了我以下错误:
Type 'Node[]' is not assignable to type 'never[]'.
Type 'Node' is not assignable to type 'never'.
40 const dummyGraph = testGraph({ nodes: new Array(new Node(0)) });
~~~~~
我似乎无法理解为什么这会自动推断“从不”类型。我尝试明确声明类型,但没有运气。
解决方法
This discussion on Github 阐明了这个问题:
这是由 strict
和 noImplicitAny: false
的组合引起的。一般来说,我们期望如果 strict
打开,noImplicitAny
也打开;这组特定的设置会暴露一些奇怪的行为。如果两者都打开,您会看到关于 []
被隐式 any[]
; 的错误。如果两者都关闭;我们将使用控制流分析并将数组视为 push(1); 之后的 number[]
。
设置的特定组合 ( "strict": true,"noImplicitAny": false,
) 意味着我们不允许自己使用控制流分析或允许数组隐式 any[]
,因此 never[]
是唯一的剩余的允许选项。
如果您不打算打开 strict
,我建议您关闭 noImplicitAny
。
所以,这可能是一个可能的出路
export function testGraph({ id = 0,name = "test",nodes = [] as Array<Node> }): Graph {
...
,
nodes = []
。什么数组?
[]
永远不足以让 typescript 推断数组类型,在这种特殊情况下被推断为 never[]
。因此,通常,您只需为整个解构对象提供一个类型,并包含正确的数组类型:
export function testGraph({
id = 0,nodes = []
}: {
id?: number,name?: string,nodes?: Node[]
}): Graph {
//...
}
或者使用 generics 从调用者推断。
export function testGraph<T>({
id = 0,nodes?: T[]
}): Graph<T> {
//...
}
请注意,您可能还希望将 Graph
设为泛型,以便您传递给 testGraph
的节点类型也可以反映在 Graph
的节点中。
这可能看起来像:
class Graph<T> {
constructor(id: number,name: string,nodes: T[]) {
//...
}
}