区分元组无法按预期工作

时间:2019-07-02 10:11:28

标签: typescript overloading

我刚刚从this question的答案中学到了使用区分元组作为参数的方法,但是当我在一些旧代码上尝试使用该概念时,我发现我无法使其正常工作预期。考虑以下示例:

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]类型,接下来的两行应该没有问题,但这不是案件。为什么会这样?如何在仍然使用元组想法的情况下解决此问题?

1 个答案:

答案 0 :(得分:1)

问题在于此元组实际上不是受歧视的联合。受歧视的联合必须具有判别属性,如果满足以下条件,则该属性就是判别属性:

  1. 该属性是文字类型,如此处9163
  2. 所述
  3. 如果联合类型的属性具有至少包含一个单位类型且没有此处概述的可实例化类型的联合类型,则该联合类型的属性为可判别属性27695

请参阅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
    }
}