typescript 使用用户定义的typeguard时,类型“A”上不存在属性

ecbunoof  于 2023-01-14  发布在  TypeScript
关注(0)|答案(1)|浏览(155)

我正在使用用户定义的type guard来检查我的对象类型,如这里所描述的,docs中的例子非常简单,运行良好,但是当我在另一个“check”函数中使用typeguard时,我的问题开始出现。
我准备了下面这个问题的一个最小的例子:

export interface A {
  a: string;
}

export interface B extends A {
  b: string;
  c: string;
}

// check if example has b and c.
export const isB = (example: A | B): example is B => {
  return (<B>example).b !== undefined && (<B>example).c !== undefined;
};

// check if example has b and c and c equals 'foo'.
export const cEqualsFoo = (example: A | B): boolean => {
  return isB(example) && example.c === "foo";
};

我使用的是Vue2,在我的组件中,我定义了一个prop,如下所示,我使用的是我的类型保护方法:

x: {
    type: Object as PropType<A> | PropType<B>
}

// later, in the method
if (isB(this.x)) {
    // works!
    console.log(this.x.b);
}

if (cEqualsFoo(this.x)) {
    console.log(this.x.a);
    console.log(this.x.b); // does not work - typescript throws "Property 'b' does not exist on type 'A'.
    console.log(this.x.c); // does not work - typescript throws "Property 'c' does not exist on type 'A'.

}

看起来isB函数检查工作了,但是cEqualsFoo函数没有,因为它抛出了我在上面注解代码部分粘贴的打字错误。这对我来说很奇怪,因为cEqualsFoo函数在幕后使用了isB函数。
问题的原因是什么?我如何解决它?

roejwanj

roejwanj1#

虽然您可以复制类型 predicate 以反映cEqualsFooisB的用法,

export const cEqualsFoo = (example: A | B): example is B => {

更好的替代方案是将cEqualsFoo更改为仅采用B

export const cEqualsFoo = (example: B): boolean => {
  return example.c === "foo";
};

因此,必须将isBcEqualsFoo结合使用:

if (isB(this.x) && cEqualsFoo(this.x)) {

相关问题