I know how to infer types in this case:
import PropTypes from 'prop-types';
const props = {
id: PropTypes.number,
};
type Props = PropTypes.InferProps<typeof props>;
const x: Props = {};
x.id; // number | null | undefined
However, in my case I have
const propsShape = PropTypes.shape({
id: PropTypes.number,
// more properties including nested PropTypes.shape calls
});
If I try to
type PropsFromShape = PropTypes.InferProps<typeof propsShape>;
const y: PropsFromShape = {};
const z = y.id;
it doesn't compile:
Type '{}' is not assignable to type 'PropsFromShape'.
Property 'isRequired' is missing in type '{}' but required in type 'InferPropsInner<Pick<Requireable<InferProps<{ id: Requireable<number>; }>>, "isRequired">>'.
Property 'id' does not exist on type 'PropsFromShape'.
I could extract the argument of shape
into a separate constant and work as above, but is there a nice way to infer the property types directly from propsShape
?
To get the type of the nested object, you can use type NestedProps = PropTypes.InferProps<typeof propsShape>['isRequired'];
import PropTypes from "prop-types";
const propsShape = PropTypes.shape({
nestedId: PropTypes.number,
// more properties including nested PropTypes.shape calls
});
const props = {
id: PropTypes.number,
optionalWithShape: propsShape
};
type Props = PropTypes.InferProps<typeof props>;
type NestedProps = PropTypes.InferProps<typeof propsShape>['isRequired'];
const x: Props = {};
x.id = 1;
const y: NestedProps = {
nestedId: 1
}
x.optionalWithShape = y;
Alternatively, if you can have entire props definition in one place:
import PropTypes from "prop-types";
const props = {
id: PropTypes.number,
optionalWithShape: PropTypes.shape({
nestedId: PropTypes.number
})
};
type Props = PropTypes.InferProps<typeof props>;
type NestedProps = Props['optionalWithShape'];
const x: Props = {};
x.id = 1;
const y: NestedProps = {
nestedId: 1
}
x.optionalWithShape = y;
console.log(x.optionalWithShape.nestedId);
The latter reads better IMHO.