Typescript Interface - Possible to make "one or the other" properties required?
If you're truly after "one property or the other" and not both you can use never
in the extending type:
interface MessageBasics {
timestamp?: number;
/* more general properties here */
}
interface MessageWithText extends MessageBasics {
text: string;
attachment?: never;
}
interface MessageWithAttachment extends MessageBasics {
text?: never;
attachment: string;
}
type Message = MessageWithText | MessageWithAttachment;
// ð OK
let foo: Message = {attachment: 'a'}
// ð OK
let bar: Message = {text: 'b'}
// ❌ ERROR: Type '{ attachment: string; text: string; }' is not assignable to type 'Message'.
let baz: Message = {attachment: 'a', text: 'b'}
Example in Playground
You can use a union type to do this:
interface MessageBasics {
timestamp?: number;
/* more general properties here */
}
interface MessageWithText extends MessageBasics {
text: string;
}
interface MessageWithAttachment extends MessageBasics {
attachment: Attachment;
}
type Message = MessageWithText | MessageWithAttachment;
If you want to allow both text and attachment, you would write
type Message = MessageWithText | MessageWithAttachment | (MessageWithText & MessageWithAttachment);