You could use a higher order component (HOC) that will just change the type of the props to be optional where they are present in defaultProps
interface SomeComponentProps {
required: string;
someOptionalProperty: string;
trulyOptional?: string;
}
interface SomeComponentState { /* ... */ }
class SomeComponent extends React.Component<SomeComponentProps, SomeComponentState> {
static defaultProps = {
someOptionalProperty : 'some default value',
}
method() {
const shouldNotBeOptional = this.props.someOptionalProperty;
}
}
type SameTypeOrCustomError<T1, T2> = T1 extends T2 ? T2 extends T1 ? T1 : "Error Different Types": "Error Different Types";
type FilterOptional<T> = Exclude<{ [P in keyof T]: undefined extends T[P]? P: never }[keyof T], undefined>;
type d = FilterOptional<SomeComponentProps>
type PropsWithDefault<TProps extends TDefaults, TDefaults> =
{ [P in Exclude<keyof TProps, keyof TDefaults | FilterOptional<TProps>>]: TProps[P] } &
{ [P in keyof TDefaults | FilterOptional<TProps>]?: TProps[P] };
type ReactProps<T> = T extends React.Component<infer Props, any> ? Props: never;
type ReactState<T> = T extends React.Component<any, infer TState> ? TState: never;
type ChangeReactProps<TComponent extends React.Component<any, any>, TNewProps> = {
new (props: TNewProps, context?: any) : React.Component<TNewProps, ReactState<TComponent>>
};
function withDefaults<T extends { new (...args: any[]) : any, defaultProps: Partial<ReactProps<InstanceType<T>>> }>(ctor: T)
: ChangeReactProps<InstanceType<T>, PropsWithDefault<ReactProps<InstanceType<T>>, T['defaultProps']>> {
return ctor; // we just chage type, we can return the same class
}
const SomeComponent2 = withDefaults(SomeComponent);
let d = <SomeComponent2 required="" /> //ok
let x = <SomeComponent2 required="" trulyOptional="" /> //ok