【问题标题】:Discriminating tuple not working as expected区分元组没有按预期工作
【发布时间】:2019-07-02 10:11:28
【问题描述】:

我刚刚从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] 类型,并且接下来的两行应该没有问题,但事实并非如此。为什么会这样?如何在仍然使用元组思想的同时解决这个问题?

【问题讨论】:

    标签: typescript overloading


    【解决方案1】:

    问题是这个元组并不是真正的可区分联合。可区分联合必须具有可区分属性,如果满足以下条件,则该属性是可区分属性:

    1. 该属性是一个文字类型,如此处所述9163
    2. 如果联合类型的联合类型包含至少一个单元类型且没有此处所述的可实例化类型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
        }
    }
    

    【讨论】:

    • 我明白了,但为什么第二个条件是这样表述的?你能解释一下不需要实例化类型的原因吗?
    • @Mu-TsunTsai 我链接到的 PR 是我对这些决策过程的所有见解。我不确定允许类和instanceof 区分工会是否存在健全性问题或实现问题,或者是否有足够的需求来实现问题。我只能告诉你,判别属性必须是什么样子才能工作?
    猜你喜欢
    • 2021-03-16
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多