При работе с типами объединения обычно проще всего создать ADT с теговым объединением.Однако иногда это невозможно.
Типичным примером является компонент <Route/>
React Router.Здесь есть три дополнительных параметра: component
, render
и children
, но должно быть 1 и ровно 1 из этих 3 пройденных.
Для простоты я сократил типы здесь, но опубликованные в настоящее время типы выглядят примерно так:
interface Route {
render?: string
component?: string
children?: string
someOtherProps?: any
}
Они должны действительно быть похожими на это:
interface BetterRouteRender extends Route {
render: string
component?: undefined
children?: undefined
}
interface BetterRouteComponent extends Route {
render?: undefined
component: string
chldren?: undefined
}
interface BetterRouteChildren extends Route {
render?: undefined
component?: undefined
Children: string
}
type BetterRoute =
| BetterRouteRender
| BetterRouteComponent
| BetterRouteChildren
const invalidRouteBecauseEmpty: BetterRoute = {}
const invalidRouteBecauseDupe: BetterRoute = { render: 'render', component: 'component' }
const validRoute: BetterRoute = { render: 'render' }
Итак, два вопроса:
- Есть ли лучший способ справиться с вышеперечисленным?
- Если нет, я ищу помощь, пытаясь написать такой тип:
type BetterOptionalTypeConstructor<T, KS extends Array<keyof T>> = unknown
... который использовал бы что-то вроде BetterOptionalTypeConstructor<Route, ['render', 'component', 'children']>
, и выплюнул бы тип BetterRoute
, показанный выше.
Я пока не приложил много усилий, но похоже, что Typescript ненасколько я могу судить, в настоящее время не поддерживает "типы сопоставленных объединений".Любое понимание этого фронта будет оценено!