Reputation: 556
How to get rid of or operator (|
) and merge all object properties to be all accessible?
Because now, typing payload.signInMethod
TS complaints that this method does not exist in none "or group" but this one. How to write type to merge all object keys?
Upvotes: 0
Views: 279
Reputation: 249536
The usual way to deal with union types is to use type guards to narrow the union down to one of the members. In this case the in
type guard works best:
type Context = {
EventApplication: {
applicationPhase: string;
};
SignInRef: {
signInMethod: 'google' | 'facebook' | 'yahoo' | 'username';
};
ExpressCheckout: {
paymentMethodPresent: boolean;
shippingAddressPresent: boolean;
receivePartnerEmails: boolean;
promoCode: string;
}
}
const getContext = (payload: Context[keyof Context]) => {
if('signInMethod' in payload) {
payload.signInMethod;
} else if('applicationPhase' in payload) {
payload.applicationPhase
} else{
payload.promoCode
}
}
Now if you really want to have access to all members directly on payload
, some | undefined
will by necessity have to creep into the property types (since a property might be undefined
on a specific union member). We can adapt StrictUnion
from here to get the types to work the way you want:
type UnionKeys<T> = T extends any ? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, undefined>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>
type Context = {
EventApplication: {
applicationPhase: string;
};
SignInRef: {
signInMethod: 'google' | 'facebook' | 'yahoo' | 'username';
};
ExpressCheckout: {
paymentMethodPresent: boolean;
shippingAddressPresent: boolean;
receivePartnerEmails: boolean;
promoCode: string;
}
}
const getContext = (payload: StrictUnion<Context[keyof Context]>) => {
payload.applicationPhase // string | undefined
}
Upvotes: 2