区分元组未按预期工作
Discriminating tuple not working as expected
我刚刚从的回答中学到了使用鉴别元组作为参数的方法,但是当我在我的一些旧代码上尝试这个概念时,我发现我无法让它工作如我所料。考虑以下示例:
class Fraction {
constructor(r: Rational) {
/* Not important */
}
}
type Rational = number | Fraction;
class Couple {
private _x: Fraction;
private _y: Fraction;
constructor(c: Couple);
constructor(x: Rational, y: Rational);
constructor(...r: [Couple] | [Rational, Rational]) {
if(r[0] instanceof Couple) r = [r[0]._x, r[0]._y]; // pay attention here
this._x = new Fraction(r[0]);
this._y = new Fraction(r[1]);
}
}
我预计,在上面指示的行之后,TypeScript 应该得出结论 r
只能是 [Rational, Rational]
类型并且接下来的两行应该没有问题,但那是不是这样的。为什么会这样,如何在仍然使用元组想法的同时解决这个问题?
问题在于这个元组并不是真正的可区分联合。一个判别联合必须有一个判别式 属性,一个 属性 是一个判别式 属性 如果:
查看this评论
如果我们向第一个元组添加一个额外的元素,我们可以将其转换为可区分的联合,从而满足上面概述的第二种情况:
class Fraction {
constructor(r: Rational) {
/* Not important */
}
}
type Rational = number | Fraction;
class Couple {
private _x: Fraction;
private _y: Fraction;
constructor(c: Couple);
constructor(x: Rational, y: Rational);
constructor(...r: [Couple, undefined?] | [Rational, Rational]) {
if(r[1] === undefined) r = [r[0]._x, r[0]._y];
this._x = new Fraction(r[0]); // ok
this._y = new Fraction(r[1]); // ok
}
}
我刚刚从
class Fraction {
constructor(r: Rational) {
/* Not important */
}
}
type Rational = number | Fraction;
class Couple {
private _x: Fraction;
private _y: Fraction;
constructor(c: Couple);
constructor(x: Rational, y: Rational);
constructor(...r: [Couple] | [Rational, Rational]) {
if(r[0] instanceof Couple) r = [r[0]._x, r[0]._y]; // pay attention here
this._x = new Fraction(r[0]);
this._y = new Fraction(r[1]);
}
}
我预计,在上面指示的行之后,TypeScript 应该得出结论 r
只能是 [Rational, Rational]
类型并且接下来的两行应该没有问题,但那是不是这样的。为什么会这样,如何在仍然使用元组想法的同时解决这个问题?
问题在于这个元组并不是真正的可区分联合。一个判别联合必须有一个判别式 属性,一个 属性 是一个判别式 属性 如果:
查看this评论
如果我们向第一个元组添加一个额外的元素,我们可以将其转换为可区分的联合,从而满足上面概述的第二种情况:
class Fraction {
constructor(r: Rational) {
/* Not important */
}
}
type Rational = number | Fraction;
class Couple {
private _x: Fraction;
private _y: Fraction;
constructor(c: Couple);
constructor(x: Rational, y: Rational);
constructor(...r: [Couple, undefined?] | [Rational, Rational]) {
if(r[1] === undefined) r = [r[0]._x, r[0]._y];
this._x = new Fraction(r[0]); // ok
this._y = new Fraction(r[1]); // ok
}
}