[英]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.