对象解构导致 TypeScript 中的 'never' 类型
Object destructing resulting in 'never' type in TypeScript
我的代码如下:
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, name, nodes);
}
export function testDatabase({ id = 0, name = "test", graphs = [] }): Database {
if (graphs.length === 0) {
const dummyGraph = testGraph({ nodes: new Array(new Node(0)) });
return new Database(id, name, [dummyGraph]);
}
return new Database(id, name, 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)) });
~~~~~
我似乎无法理解为什么这是自动推断 'never' 类型。我尝试明确声明类型但没有成功。
This discussion on Github 阐明了这个问题:
This is caused by the combination of strict
and noImplicitAny: false
. In general we expect that if strict
is on, noImplicitAny
is also on; this particular set of settings will expose some odd behavior. If you had both on, you'd see an error about the []
being implicitly any[]
; if both were off; we'd use control flow analysis and treat the array as a number[]
after the push(1);.
The particular combination ( "strict": true, "noImplicitAny": false,
) of settings means that we don't allow ourselves to use control flow analysis or allow the array to be implicitly any[]
, so never[]
is the only remaining allowable option.
I'd recommend turning off strict
if you're not going to have noImplicitAny
on.
所以,这可能是一个可行的出路
export function testGraph({ id = 0, name = "test", nodes = [] as Array<Node> }): Graph {
...
nodes = []
。什么数组?
[]
永远不足以让打字稿推断数组类型,在这种特殊情况下被推断为 never[]
。因此,通常情况下,您只需为整个解构对象提供一个类型,并包括适当的数组类型:
export function testGraph({
id = 0,
name = "test",
nodes = []
}: {
id?: number,
name?: string,
nodes?: Node[]
}): Graph {
//...
}
或使用generics从调用者推断。
export function testGraph<T>({
id = 0,
name = "test",
nodes = []
}: {
id?: number,
name?: string,
nodes?: T[]
}): Graph<T> {
//...
}
请注意,您可能还想使 Graph
通用,以便您传递给 testGraph
的节点类型可以反映在 Graph
的节点中嗯
这可能看起来像:
class Graph<T> {
constructor(id: number, name: string, nodes: T[]) {
//...
}
}
我的代码如下:
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, name, nodes);
}
export function testDatabase({ id = 0, name = "test", graphs = [] }): Database {
if (graphs.length === 0) {
const dummyGraph = testGraph({ nodes: new Array(new Node(0)) });
return new Database(id, name, [dummyGraph]);
}
return new Database(id, name, 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)) });
~~~~~
我似乎无法理解为什么这是自动推断 'never' 类型。我尝试明确声明类型但没有成功。
This discussion on Github 阐明了这个问题:
This is caused by the combination of
strict
andnoImplicitAny: false
. In general we expect that ifstrict
is on,noImplicitAny
is also on; this particular set of settings will expose some odd behavior. If you had both on, you'd see an error about the[]
being implicitlyany[]
; if both were off; we'd use control flow analysis and treat the array as anumber[]
after the push(1);.The particular combination (
"strict": true, "noImplicitAny": false,
) of settings means that we don't allow ourselves to use control flow analysis or allow the array to be implicitlyany[]
, sonever[]
is the only remaining allowable option.I'd recommend turning off
strict
if you're not going to havenoImplicitAny
on.
所以,这可能是一个可行的出路
export function testGraph({ id = 0, name = "test", nodes = [] as Array<Node> }): Graph {
...
nodes = []
。什么数组?
[]
永远不足以让打字稿推断数组类型,在这种特殊情况下被推断为 never[]
。因此,通常情况下,您只需为整个解构对象提供一个类型,并包括适当的数组类型:
export function testGraph({
id = 0,
name = "test",
nodes = []
}: {
id?: number,
name?: string,
nodes?: Node[]
}): Graph {
//...
}
或使用generics从调用者推断。
export function testGraph<T>({
id = 0,
name = "test",
nodes = []
}: {
id?: number,
name?: string,
nodes?: T[]
}): Graph<T> {
//...
}
请注意,您可能还想使 Graph
通用,以便您传递给 testGraph
的节点类型可以反映在 Graph
的节点中嗯
这可能看起来像:
class Graph<T> {
constructor(id: number, name: string, nodes: T[]) {
//...
}
}