打字稿:使用嵌套的只读属性时,类型防护不能按预期工作

时间:2018-04-20 10:28:35

标签: typescript

Quality可能有好有坏,具体取决于类型。这里打字卫士工作正常

enum GoodBad {
    Good = 'Good',
    Bad = 'Bad'
}
interface IQuality {
    readonly type: GoodBad;
}
interface GoodQuality extends IQuality {
    readonly type: GoodBad.Good;
}
interface BadQuality extends IQuality {
    readonly type: GoodBad.Bad;
}
type Quality = GoodQuality | BadQuality;

let quality: Quality;
if (quality.type == GoodBad.Good) {
    let goodQuality: GoodQuality = quality; // No Problem. Working good.
    let badQuality: BadQuality = quality; // Throw error. Working good.
}

但现在当我在Product中包装质量时

interface IProduct {
    readonly quality: Quality;
}

interface GoodProduct extends IProduct {
    readonly quality: GoodQuality;
}
interface BadProduct extends IProduct {
    readonly quality: BadQuality;
}

type Product = GoodProduct | BadProduct;
let product: Product;
if (product.quality.type == GoodBad.Good) {
    let goodProduct: GoodProduct = product; // Throw error. Working Bad.
    // let badProduct: BadProduct = product; // Throw error. Working fine.
}

防护罩不能按预期工作。

  1. 这个if阻止和前一个if阻止的差异是什么?
  2. let goodProduct: GoodProduct = product;为什么会抛出错误?
  3. 一种解决方案是在readonly type: GoodBad上创建另一个IProduct。但这是额外的,可以消除吗?

1 个答案:

答案 0 :(得分:2)

类型后卫会影响quality字段,而不会影响product变量。类型保护仅影响拥有区分字段的字段;它不会影响所有者。

这样可行:

type Product = GoodProduct | BadProduct;
let product!: Product;
if (product.quality.type == GoodBad.Good) {
    let goodQuality: GoodQuality = product.quality; // Ok
    let badQuality: BadQuality = product.quality; // Err
    let goodProduct: GoodProduct = product; // Err, product not affected
    let badProduct: BadProduct = product; // Err, product not affected
}

您添加额外字段的解决方案是好的,另一个是创建自定义类型保护:

function isGoodProduct(p: Product)  : p is GoodProduct {
    return p.quality.type ===  GoodBad.Good
}
if (isGoodProduct(product)) {
    let goodProduct: GoodProduct = product; // OK
    let badProduct: BadProduct = product; // Err
}