Require one of two properties

What would you folks say is a clean way to accomplish that either userToken or ConversationId are set in my type without requiring both? πŸ€”
export type PostChatData = {
command: Extract<ChatCommand, 'POST'>;
userToken: string;
conversationId: string;
type: ChatType;
// other crap
};
export type PostChatData = {
command: Extract<ChatCommand, 'POST'>;
userToken: string;
conversationId: string;
type: ChatType;
// other crap
};
14 Replies
deforestor
deforestorβ€’2y ago
Interesting question, it seems like no matter what we do, it won't be 100%, but you can achieve it like this:
deforestor
deforestorβ€’2y ago
but no matter what I try, it'll always show the other one:
deforestor
deforestorβ€’2y ago
But at least you get an error if you do fill it
Wezter
Wezterβ€’2y ago
I need to use that logic in like 10 different types for a lot of my request models, I'll try this suggestion but seems a bit ugly to have to add both types to all the types πŸ€” @deforestor what do you think about this?
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
}[Keys];

type ConversationIdOrUserToken = RequireAtLeastOne<ChatAuth, 'userToken' | 'conversationId'>;
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
}[Keys];

type ConversationIdOrUserToken = RequireAtLeastOne<ChatAuth, 'userToken' | 'conversationId'>;
And then I just do & ConversationIdOrUserToken to all of them.
deforestor
deforestorβ€’2y ago
I tried that one too, but..
deforestor
deforestorβ€’2y ago
it doesn't show me the error
Brendonovich
Brendonovichβ€’2y ago
How about this?
export type PostChatData = {
command: "POST";
} & ({ userToken: string } | { conversationId: string }) & {
userToken?: string;
conversationId?: string;
}
export type PostChatData = {
command: "POST";
} & ({ userToken: string } | { conversationId: string }) & {
userToken?: string;
conversationId?: string;
}
Could probs be turned into a helper
Unknown User
Unknown Userβ€’2y ago
Message Not Public
Sign In & Join Server To View
Brendonovich
Brendonovichβ€’2y ago
I think it’s from another SO, looks the same tho
Unknown User
Unknown Userβ€’2y ago
Message Not Public
Sign In & Join Server To View
Wezter
Wezterβ€’2y ago
Wouldn't what I sent earlier work?
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
}[Keys];

type ConversationIdOrUserToken = RequireAtLeastOne<ChatAuth, 'userToken' | 'conversationId'>;
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
}[Keys];

type ConversationIdOrUserToken = RequireAtLeastOne<ChatAuth, 'userToken' | 'conversationId'>;
And then I just do & ConversationIdOrUserToken to all of them.
deforestor
deforestorβ€’2y ago
can you show how it looks on the editor?
Wezter
Wezterβ€’2y ago
Want results from more Discord servers?
Add your server