I'm trying to add types to an existing React component which can render down to either an input
or a textarea
based on the optional textArea
prop. I tried to create a discriminated union to properly account for the differing passthrough props, but TypeScript does not seem to handle a missing discriminant the same as an undefined
discriminant. This is the only case I've seen where TypeScript distinguishes missing vs undefined
.
Is there a way to get discrimination to work for a missing property?
This answer mentions that a discriminant must be non-optional, but that doesn't seem to be documented as far as I can tell, so I'm unsure if this is a TS bug or not.
Minimal repro:
interface NumProps {
isString?: false
onChange: (value: number) => void
}
interface StringProps {
isString: true,
onChange: (value: string) => void
}
type Props = NumProps | StringProps
const props: Props = {
// Error: Parameter 'value' implicitly has an 'any' type.
// Expected: 'value' is inferred as 'number'.
onChange: value => {},
}
const propsUndefined: Props = {
isString: undefined,
// OK: 'value' is inferred as 'number'.
onChange: value => {},
}
Summary of the goal:
type InlineInputProps = { textArea?: false } & React.InputHTMLAttributes<HTMLInputElement>
type TextareaProps = { textArea: true } & React.TextareaHTMLAttributes<HTMLTextAreaElement>
type InputProps = InlineInputProps | TextareaProps