tapuscrit de l'interface de demander à l'une des deux propriétés d'exister
Je suis en train de créer une interface qui pourrait avoir
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
- Est-il un moyen d'exiger
component
ouclick
être mis - Est-il un moyen d'exiger que les deux propriétés ne peuvent pas être ensemble?
Vous devez vous connecter pour publier un commentaire.
Pas avec une seule interface, car les types n'ont aucune logique conditionnelle et ne peut pas dépendre les uns des autres, mais vous pouvez en divisant les interfaces:
AND
etOR
opérateurs pour ses types. Si vous êtes en train de faire quelque chose comme cela, OU peut être agréable pour vous donner un seul recueillies nom après la déclaration d'un tas de différents types.component
etclick
l'habitude de faire une erreur...click?: never
surComponentMenuItem
etcomponent?: never
surClickMenuItem
.Avec l'aide de la
Exclude
type qui a été ajouté à la Machine 2.8, un généralisables façon à exiger qu'au moins l'un d'un ensemble de propriétés est fourni est:Et partielle, mais pas de manière absolue exiger que l'un et un seul est fourni est:
Voici un Tapuscrit de l'aire de jeux lien montrant à la fois dans l'action.
La mise en garde avec
RequireOnlyOne
est que la Machine ne savent pas toujours au moment de la compilation de tous les biens qui existent au moment de l'exécution. Alors, évidemment,RequireOnlyOne
ne peut rien faire pour empêcher les autres propriétés qu'il ne connaît pas. J'ai fourni un exemple de la façon dontRequireOnlyOne
peut manquer des choses à la fin de l'aire de jeux lien.Un aperçu rapide de la façon dont il fonctionne à l'aide de l'exemple suivant:
Pick<T, Exclude<keyof T, Keys>>
deRequireAtLeastOne
devient{ title: string, icon: string}
, qui sont à l'identique des propriétés de la touches pas inclus dans'click' | 'component'
{ [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys]
deRequireAtLeastOne
devientQui devient
Qui devient finalement
L'intersection des étapes 1 et 2 ci-dessus
simplifie à
component
etclick
un type, puis d'autresany
un objet à la fois avec au moins un ensemble de propriétés valides va passer. Je suppose que c'est à cause de la façon dont le type se réduit à{ title: string, icon: string, component: any} | { title: string, icon: string, click: any}
Qui stipule que le type est de 3 propriétés au lieu de 4 avec un cours facultatif. Je suis en train d'essayer de trouver de la documentation sur l'utilisation de la matrice dans la carte de notation, mais ne peut pas.& Partial<Pick<T, Exclude<Keys, K>>>
àRequireAtLeastOne
. J'ai aussi mis de l'aire de jeux lien pourcomponent
etclick
sontnumber
plutôt les types deany
pour montrer un exemple de maintenant correctement déclaration d'un objet non valide dans le cas où vous l'apporter. Merci![K in keys]-
n'?K
dans l'objet d'origineT
. Voir stackoverflow.com/questions/49655419/... Comme à son objectif dans[K in Keys]-?:
plus précisément: j'ai juste fait quelques tests et il semble que ça ne fait pas de différence dans le résultat final, mais je l'ai mis juste pour être certain queRequireAtLeastOne
se comporte de la même façon, indépendamment de savoir si les propriétés spécifiées pourKeys
étaient à l'origine en option ou pas.Une alternative sans de multiples interfaces est
J'ai posé une question similaire à Comment créer un Partiel-comme qui nécessite une seule propriété à définir
Ci-dessus peut être simplifié, mais il peut ou ne peut pas être plus facile à lire
Noter qu'aucun de ces vous empêcher d'ajouter à la fois parce que la Machine ne permettent propriétés supplémentaires sur les objets que l'utilisation ET/OU de Voir https://github.com/Microsoft/TypeScript/issues/15447
&
et de l'extrait detitle
eticon
à un type distinct. 🙂J'aime utiliser
Pick
avec un type de base comprend toutes les propriétés de mettre en place ces types de mise en exigences.C'est propre et également flexible. Vous pouvez obtenir arbitrairement complexes avec vos besoins, en affirmant des choses comme "exigent de toutes les propriétés, juste ces deux propriétés, ou seulement celui de la propriété" et ainsi de suite tout en gardant votre déclaration simple et lisible.
Que j'ai fait:
Ensuite, j'ai utilisé:
Mais espérais qu'il y avait un moyen de le modéliser avec une seule interface.
<MenuItemComponent|MenuItemClick>[]