声明顺序是否会影响 TypeScript 类型推导?
Should the declaration order affect TypeScript type deduction?
似乎 TypeScript 的翻译器在某种程度上依赖于声明的顺序,至少在重载函数的情况下是这样。
假设我们有 类 用于 2 维和 3 维向量:
class Vector2 {
public get x() : number
public get y() : number
}
class Vector3 {
public get x() : number
public get y() : number
public get z() : number
}
我们有一个重载函数,它接受 Vector2
或 Vector3
:
function add(a : Vector2, b : number) : Vector2;
function add(a : Vector3, b : number) : Vector3;
根据 add()
的哪个签名先出现 - 带有 Vector2
或 Vector3
结果 - 编译器可能会推断出不同类型的结果,即使我们准确地作为参数传递Vector3
。
例如,如果订单与上述相同,则代码如下:
const r = add(new Vector3, 5)
将returnVector2
代替Vector3
。
因此,如果我们将 r
的可能类型限制为 Vector3
:
const r : Vector3 = add(new Vector3, 5)
代码无法编译。
这是应该的吗?因为对我来说,这看起来像是翻译器的错误。
这是 Typescript 的预期行为:当您调用重载函数时,编译器会选择 first 在调用点兼容的重载签名,而不是 最具体 签名。来自 the docs:
TypeScript chooses the first matching overload when resolving function calls. When an earlier overload is “more general” than a later one, the later one is effectively hidden and cannot be called.
因为你的 Vector3
是你的 Vector2
的 structural subtype,Vector3
重载签名更具体所以你应该在 [=11= 之前写那个] 重载签名。
似乎 TypeScript 的翻译器在某种程度上依赖于声明的顺序,至少在重载函数的情况下是这样。
假设我们有 类 用于 2 维和 3 维向量:
class Vector2 {
public get x() : number
public get y() : number
}
class Vector3 {
public get x() : number
public get y() : number
public get z() : number
}
我们有一个重载函数,它接受 Vector2
或 Vector3
:
function add(a : Vector2, b : number) : Vector2;
function add(a : Vector3, b : number) : Vector3;
根据 add()
的哪个签名先出现 - 带有 Vector2
或 Vector3
结果 - 编译器可能会推断出不同类型的结果,即使我们准确地作为参数传递Vector3
。
例如,如果订单与上述相同,则代码如下:
const r = add(new Vector3, 5)
将returnVector2
代替Vector3
。
因此,如果我们将 r
的可能类型限制为 Vector3
:
const r : Vector3 = add(new Vector3, 5)
代码无法编译。
这是应该的吗?因为对我来说,这看起来像是翻译器的错误。
这是 Typescript 的预期行为:当您调用重载函数时,编译器会选择 first 在调用点兼容的重载签名,而不是 最具体 签名。来自 the docs:
TypeScript chooses the first matching overload when resolving function calls. When an earlier overload is “more general” than a later one, the later one is effectively hidden and cannot be called.
因为你的 Vector3
是你的 Vector2
的 structural subtype,Vector3
重载签名更具体所以你应该在 [=11= 之前写那个] 重载签名。