[英]Typescript/Angular 10: component with generic union type
我有以下接口:
export interface Channel {
id: number;
name: string;
}
export interface TvChannel extends Channel {
subscribed: boolean;
}
export interface RadioChannel extends Channel {
// marker interface to distinguish radio channels from TV channels
}
和一个 angular 组件:
// ./channel.ts
@Component({
selector: 'channel',
templateUrl: './channel.html'
})
export class ChannelComponent<T extends TvChannel | RadioChannel> {
@Input() channel: T;
(...)
}
使用以下模板
<!-- ./channel.html -->
<div>{{ channel.id }} </div>
<div *ngIf="channel.subscribed !== undefined">{{ channel.subscribed }} </div>
我的问题是我在模板上遇到编译错误,因为无法解析channel.subscribed
。 我知道它适用于channel.id
,因为这是TvChannel
和RadioChannel
类型(即这些类型之间的交集)中的属性。 但是我想要一个可以处理这两种类型的组件(即两种类型的联合)。
这可能吗?
当你做这样的联合时——你最终得到的 T 只是可分配给 TvChannel 和 RadioChannel 的类型。 从您的 inheritance 设置中,这只会是频道。
您可以使用类型保护来处理这种行为 - https://www.typescriptlang.org/docs/handbook/advanced-types.html - 您使用类型保护来断言您的类型实际上是一种类型或另一种类型。
但是,根据您的代码,我认为这不是您所追求的确切行为。
您似乎想要类型的联合 - 其中特定类型特有的属性是可选的,而共享的属性是在 Channel 中定义的。
这是我输入的方式。 我已将属性 foo 添加到 RadioChannel 以测试它的行为是否正确
类型:
export interface Channel {
id: number;
name: string;
}
export interface TvChannel extends Channel {
subscribed: boolean;
}
export interface RadioChannel extends Channel {
// marker interface to distinguish radio channels from TV channels
foo: string;
}
帮手类型。 这里的想法是构造两组密钥。 UniqueKeys<T, U> 是一组键,仅存在于一个 object 或另一个上,但不存在于两者上。 CommonKeys<T, U> 则相反。
type UniqueKeys<T, U> = Exclude<keyof T, keyof U> | Exclude<keyof U, keyof T>;
// Test unique keys
type ChannelUniqueKeys = UniqueKeys<TvChannel, RadioChannel>; // "subscribed" | "foo"
type CommonKeys<T, U> = keyof T & keyof U;
// Test common keys
type ChannelCommonKeys = CommonKeys<TvChannel, RadioChannel>; // "id" | "name"
现在我们根据这两个键集将它们重建回 object 个切片,从 (T & U) 中查找正确的值——两种类型的组合。
type UniqueObjectSlice<T, U> = {[key in UniqueKeys<T, U>]: (T & U)[key]};
type CommonObjectSlice<T, U> = {[key in CommonKeys<T, U>]: (T & U)[key]};
最后我们可以构造 PartialUnion<T, U>。 现在这只是独特的 object 切片的部分(使所有属性都可选),结合了公共的 object 切片:
type PartialUnion<T, U> = Partial<UniqueObjectSlice<T, U>> & CommonObjectSlice<T, U>;
我已将其附加到 function 只是为了检查它是否正常工作 - 但只需为 class 子 myComponent ,您应该会得到预期的行为。
function myComponent<T extends PartialUnion<TvChannel, RadioChannel>>(properties: T) {
// Unique keys
type foo = typeof properties.foo; // string | undefined
type subscribed = typeof properties.subscribed; // boolean | undefined
// Common keys
type id = typeof properties.id; // number
type name = typeof properties.name; // string
}
游乐场链接
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.