ExcludeTypeScript 2.8'de eklenen tür yardımıyla, bir dizi özellikten en az birini gerektirmenin genelleştirilebilir bir yolu sağlanır:
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> =
Pick<T, Exclude<keyof T, Keys>>
& {
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>
}[Keys]
Ve bir ve yalnızca birinin sağlanmasını gerektirmenin kısmi, ancak kesin olmayan bir yolu şudur:
type RequireOnlyOne<T, Keys extends keyof T = keyof T> =
Pick<T, Exclude<keyof T, Keys>>
& {
[K in Keys]-?:
Required<Pick<T, K>>
& Partial<Record<Exclude<Keys, K>, undefined>>
}[Keys]
İşte her ikisini de eylem halinde gösteren bir TypeScript oyun alanı bağlantısı.
Bununla ilgili uyarı RequireOnlyOne, TypeScript'in çalışma zamanında var olacak her özelliği derleme zamanında her zaman bilmemesidir. Yani belli ki RequireOnlyOnebilmediği ekstra özellikleri önlemek için hiçbir şey yapamaz. RequireOnlyOneOyun alanı bağlantısının sonunda bir şeyleri nasıl gözden kaçırabileceğime dair bir örnek verdim .
Aşağıdaki örneği kullanarak nasıl çalıştığına hızlı bir genel bakış:
interface MenuItem {
title: string;
component?: number;
click?: number;
icon: string;
}
type ClickOrComponent = RequireAtLeastOne<MenuItem, 'click' | 'component'>
Pick<T, Exclude<keyof T, Keys>>dan RequireAtLeastOneolur { title: string, icon: string}bulunmayan tuşların değişmeden özellikleri olan,'click' | 'component'
{ [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys]dan RequireAtLeastOneolur
{
component: Required<{ component?: number }> & { click?: number },
click: Required<{ click?: number }> & { component?: number }
}[Keys]
Hangisi olur
{
component: { component: number, click?: number },
click: { click: number, component?: number }
}['component' | 'click']
Hangi nihayet olur
{component: number, click?: number} | {click: number, component?: number}
Yukarıdaki 1. ve 2. adımların kesişimi
{ title: string, icon: string}
&
({component: number, click?: number} | {click: number, component?: number})
basitleştirir
{ title: string, icon: string, component: number, click?: number}
| { title: string, icon: string, click: number, component?: number}