i have a props that looks like:
{
option1,
option2,
option3,
option4,
general,
otheprops
}
what i want is to make it that only only one option can be used at giving time what i have as types :
interface MyTypes {
option1: boolean
option2: boolean
option3: boolean
general: boolean
otherprops: string
}
What i tried to do is:
interface GeneralTypes{
general: boolean
otherprops: string
}
interface Option1Types{
option1: boolean
}
interface Option2Types{
option2: boolean
}
interface Option3Types{
option3: boolean
}
type MyTypes = GeneralTypes & ( Option1Types | Option2Types |Option3Types )
but i get this error
Property 'option1' does not exist on type '(GeneralTypes & Option1) | (GeneralTypes & Option2)| (GeneralTypes & Option3) '
Property 'option2' does not exist on type '(GeneralTypes & Option1) | (GeneralTypes & Option2)| (GeneralTypes & Option3) '
Property 'option3' does not exist on type '(GeneralTypes & Option1) | (GeneralTypes & Option2)| (GeneralTypes & Option3) '
CodePudding user response:
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type DistinctUnion<T> =
| UnionToIntersection<T> extends infer X ? ( // save to var X
T extends any ? // split by '|'
T & { [k in Exclude<keyof X, keyof T>]?: never } // add missing keys as ?:never
: never
) : never
type x = DistinctUnion<MyTypes>
// type x = (GeneralTypes & Option1Types & {
// option2: never;
// option3: never;
// }) | (GeneralTypes & Option2Types & {
// option1: never;
// option3: never;
// }) | (GeneralTypes & ... 1 more ... & {
// ...;
// })
declare let a: x;
if (a.option1) {
a; // GeneralTypes & Option1Types
}
CodePudding user response:
here is what I've found when I need only one of the properties to be set.
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]
interface GeneralTypes {
general: boolean
otherprops: string
}
type MyTypes = GeneralTypes & RequireOnlyOne<{
option1: boolean,
option2: boolean,
option3: boolean,
}>
const props: MyTypes = {
general: false,
otherprops: '',
option1: true,
}
there is a full explanation here.