繁体   English   中英

Typescript/Angular 10:具有通用联合类型的组件

[英]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 ,因为这是TvChannelRadioChannel类型(即这些类型之间的交集)中的属性。 但是我想要一个可以处理这两种类型的组件(即两种类型的联合)。

这可能吗?

当你做这样的联合时——你最终得到的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM