Reputation: 483
I've tried countless things but couldn't get this to work
I have props for a react component, and the type of handleChange
should be a function that takes in whatever was passed as values
.
type Props<T extends Record<string, unknown> = Record<string, unknown>> = {
value: T,
handleChange: (value: T) => void
}
I'm trying to get T to be "the type of value
", but in this example they are just defaulted to Record
which is not what i want,.
This is done excessively in material ui (i.e. autocomplete)
Upvotes: 0
Views: 269
Reputation: 1905
TypeScript has a powerful inference system, which allows you to not specify the generic parameter manually but rather have it assigned based on the type of a runtime parameter. For React + TypeScript, this looks like:
type MyComponentProps<T extends Record<string, unknown>> = {
value: T;
handleChange: (value: T) => void;
};
const MyComponent = <T extends Record<string, unknown>>(
props: MyComponentProps<T>
) => {
return null;
};
class MyOtherComponent<
T extends Record<string, unknown>
> extends React.Component<MyComponentProps<T>> {
render() {
return null;
}
}
// This works
<MyComponent
value={{ a: "hi", this: { is: "a", test: true } }}
handleChange={(val) => {
console.log("val.a =", val.a, "val.this =", val.this);
}}
/>
<MyOtherComponent
value={{ a: "hi", this: { is: "a", test: true } }}
handleChange={(val) => {
val.a = val.this.is;
}}
/>
// This fails
<MyComponent
value="not a Record<string, unknown>"
handleChange={() => {}}
/>
Upvotes: 1