Using TypeScript, it is possible to create a type in which at least one of two properties is required. There are (at least) two ways to go about it: using union types and a somewhat complexer generic solution. These two solutions work well. I'm able to create and get the desired compiler error when neither of the two properties are specified.
However, when using the final type to specify the props in a react component, the compiler is unable to find the two "required" properties. Here's a simplified example:
interface Base {
text?: string;
}
interface WithId extends Base {
id: number;
}
interface WithToken extends Base {
token: string;
}
type Identifiable = WithId | WithToken | (WithId & WithToken);
//OK
const item: Identifiable = {
text: "some text"
id: 4
};
//OK
const item: Identifiable = {
token: "some token"
};
//Error
const item: Identifiable = {
text: "some text"
};
//OK
export class MyComponent extends React.Component<Identifiable, any> {
render() {
//Error (see below)
return <p>{this.props.id}</p>
}
}
The error received when trying to access one of the two required props (regardless where inside the class) looks something like this:
Property 'id' does not exist on type '(Readonly<{children?: ReactNode;}> & Readonly<WithId>) | (Readonly<{children?: ReactNode;}> & Readonly<WithToken>) | (Readonly<{children?: ReactNode;}> & Readonly<WithId & WithToken>)'
Property 'id' does not exist on type '(Readonly<{children?: ReactNode;}> & Readonly<WithToken>'.
Is there a way to work around this and have the compiler understand these requirements?
Note: using TypeScript 3.0.1, React 16.4.2, with the latest typings available to date.