Typescript: Excludeți un tip dintr-o uniune care este extins de alte tipuri din uniune
Am un tip de uniune astfel:
export type TileType =
| ProductTileType
| CustomTileType
| DealTileType
| LoadingTileType
Și un component React care trebuie să poată primi o proprietate de tip: ProductTileType | CustomTileType | DealTileType. Așa că am declarat acea proprietate cu tipul Exclude<TileType, LoadingTileType> pentru a nu permite utilizarea acelui tip aici. Singura problemă este că ProductTileType este declarat astfel:
export interface ProductTileType extends LoadingTileType { ... }
Când exclud LoadingTileType, TS vrea de asemenea să excludă orice tip care îl extinde. Cum pot evita să exclud tipurile care extind ceea ce vreau să exclud? Există un alt tip utilitar despre care nu știu?
Editare:
type MyType=Exclude<TileType, LoadingTileType> | ProductTileType ar fi o soluție rapidă pentru a rezolva problema actuală (în acest caz, ProductTileType a fost singurul care extinde LoadingTileType). Dar în viitor ar putea exista și alte tipuri care să extindă LoadingTileType. Care ar fi o modalitate mai bună de a gestiona asta?
Răspuns #1
Să spunem că avem câteva băuturi:
interface Water { healthiness: 1000 }
interface Lemonade { healthiness: 500 }
interface Tea { healthiness: 1250 } // really it depends on what kind of tea
interface Soda { healthiness: -1000 }
interface Coke extends Soda { fizziness: 1000 }
interface DrPepper extends Soda { fizziness: 800 }
interface Pepsi extends Soda { fizziness: 750 }
type Drinks = Water | Lemonade | Tea | Soda | Coke | DrPepper | Pepsi;
Acum, vreau un tip care să includă toate băuturile, cu excepția băuturii extrem de nespecifice „sodă”.
Deși aș putea pur și simplu să exclud asta și apoi să reintroduc celelalte băuturi răcoritoare (mai specifice):
type NoGenericSodaBad = Exclude<Drinks, Soda> | Coke | DrPepper | Pepsi;
Ceea ce am nevoie cu adevărat este un Exclude mai strict:
type StrictExclude<T, U> = T extends U ? U extends T ? never : T : T;
Acest tip exclude U și doar U (deși dacă treci never cu siguranță va strica unele lucruri) deoarece fiecare membru din uniunea T trebuie să fie reciproc atribuitabil lui U. Asta înseamnă că îmi pot lua băuturile fără „Soda”!
type NoGenericSodaGood = StrictExclude<Drinks, Soda>;
Teren de joacă
