打字稿:属性 'foo' 不存在于类型 'Foo | 酒吧'

贾博亚

我有一个代码,如:

// Those two come from backend, it cannot be guaranted
// they do not contain additional fields of any type.
interface Foo1 {
    name: string;
}

interface Foo2 {
    description: string;
}

// This one is mine and should always contain valid types
class Bar {
    text: string;

    constructor(data: Foo1 | Foo2 | Bar) {
        this.text = data.name || data.description || data.text;
        // Some more similar rules and throwing exceptions
        // if types are incorrect
    }
}

问题是 TypeScript 抱怨name不存在Bartext不存在Foo等等,尽管事实上无论data它们中的一个的类型肯定存在,this.text总是设置为正确的类型。

如何在此处指定打字稿类型以避免此类问题但仍接受构造函数中的两种类型?

附:我不是在问instanceof,它不适用于接口。我问的是正确注释类型,而且仅此而已。改变代码的逻辑不是我问题的答案。

提香·切尔尼科娃-德拉戈米尔

缩小联合的方法始终是类型保护您永远无法访问联合的不常见属性。

使用类型保护,您可以将代码重写为:

class Bar {
    text: string;

    constructor(data: Foo1 | Foo2 | Bar) {
        this.text = 'description' in data ? data.description:
            'name' in data ? data.name :
            data.text;
    }
}

游乐场链接

您可以创建一个自定义类型,强制所有联合成分具有所有属性,但定义为undefined. 这将允许访问公共属性:

interface Foo1 {
    name: string;
}

interface Foo2 {
    description: string;
}

type KeyOfUnion<T> = T extends T ? keyof T : never;
type ExpandUnionHelper<T, K extends PropertyKey> = T extends T ? T & Partial<Record<Exclude<K, keyof T>, undefined>> : never
type ExpandUnion<T> = ExpandUnionHelper<T, KeyOfUnion<T>>
// This one is mine and should always contain valid types
class Bar {
    text: string | undefined; 

    constructor(data: ExpandUnion<Foo1 | Foo2 | Bar>) {
        this.text = data.text || data.name || data.description
    }
}

游乐场链接

但这不会是一个确切的结果,因为它被输入为 string | undefined

最简单的解决方案可能是使用类型断言,虽然不是很优雅,但在这种情况下应该没问题。

// This one is mine and should always contain valid types
class Bar {
    text: string;

    constructor(data: Foo1 | Foo2 | Bar) {
        this.text = (data as Foo1).name || (data as Foo2).description || (data as Bar).text;
        // Some more similar rules and throwing exceptions
        // if types are incorrect
    }
}

游乐场链接

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

打字稿将类型`typeof Foo`转换为`Foo`

在声明对象后添加属性时,在 TypeScript 中获取“类型上不存在属性‘FOO’”

打字稿错误 TS2339:属性不存在于类型 (Angular 12)

属性 'onClick' 不存在于类型 '{children?: ReactNode; }'

属性'x'不存在于类型'true | 点'

属性不存在于类型上

将 tsconfig 设置为忽略“类型 'bar' 上不存在属性 'foo'。” 但仅针对特定变量

错误TS2339:类型'Observable <Foo>'和其他rxjs v.6错误不存在属性'takeUntil'

PostgreSQL“列“ foo”不存在”

反应打字稿“当前”不存在于“从不”类型中

是否可以在打字稿中将*导出为foo

仅在特定日期之后选择带有酒吧事件的foo

$ foo [“ bar”] = 1; 我可以要求PHP投诉$ foo是否不存在吗?

如果foo中不存在密钥,则忽略str.format(** foo)

[Foo.Type]数组不存在indexOf(Element)

TS2339:属性 'showNewCustomerFields' 不存在于类型 '{ newCustomer(owner: any): void; }'

Typescript 错误属性 x 不存在于类型 'Readonly<Props> & Readonly<{ children?: ReactNode; }>'

开玩笑的typescript属性模拟不存在于类型上

TSLint '属性不存在于类型' VS firefox 调试器行为

Foo <?,?,?>不是Foo <?,?,?>

null == foo与foo == null

foo(void)与foo(void *)

类型错误:无法读取 null 的属性“foo” - 对象,反应

打字稿:类型'Global'不存在属性'DB'

忽略打字稿错误“类型的值不存在属性”

打字稿:“从不”类型上不存在“用户”属性

打字稿:类型“ HTMLElement”上不存在属性“ src”

打字稿-类型“ HTMLElement”上不存在属性“ scrollY”

属性在类型上不存在。打字稿