props-type
v1.0.1
Published
Utility type that defines the type of the React component through propTypes and defaultProps in TypeScript
Downloads
2,156
Maintainers
Readme
props-type
Utility type that defines the type of the React component props through propTypes
and defaultProps
in TypeScript
Table of contents
Installation
# with NPM
$ npm install --save-dev props-type
# with Yarn
$ yarn add --dev props-type
Prerequisite
typescript
>= 2.8 (recommend 3.0+ because of support fordefaultProps
in JSX)@types/prop-types
>= 15.5.4
Usage
import PropsType from 'props-type';
// Without defaultProps
type Props = PropsType<typeof propTypes>;
// With defaultProps
type Props = PropsType<typeof propTypes, typeof defaultProps>;
Type Inference
Optional (without isRequired
)
without defaultProps
const propTypes = { disabled: PropTypes.bool };
type Props = PropsType<typeof propTypes>;
- Internal :
Props
type isdisabled: boolean | null | undefined
- External :
<Button disabled?: boolean | null | undefined />
with defaultProps
const propTypes = { disabled: PropTypes.bool };
const defaultProps = { disabled: false };
type Props = PropsType<typeof propTypes, typeof defaultProps>;
- Internal :
Props
type isboolean
- External :
<Button disabled?: boolean | undefined />
Required (with isRequired
)
without defaultProps
const propTypes = { disabled: PropTypes.bool.isRequired };
type Props = PropsType<typeof propTypes>;
- Internal :
Props
type isdisabled: boolean
- External :
<Button disabled: boolean />
with defaultProps
const propTypes = { disabled: PropTypes.bool.isRequired };
const defaultProps = { disabled: false };
type Props = PropsType<typeof propTypes, typeof defaultProps>;
- Internal :
Props
type isdisabled: boolean
- External :
<Button disabled?: boolean | undefined />
Example
without defaultProps
External
const propTypes = {
className: PropTypes.string,
disabled: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
onDoubleClick: PropTypes.func,
};
type ButtonProps = PropsType<typeof propTypes>;
// Correct
<Button disabled onClick={onClick} />
<Button className="primary" disabled onClick={onClick} />
<Button disabled onClick={onClick} onDoubleClick={onDoubleClick} />
<Button className="primary" disabled onClick={onClick} onDoubleClick={onDoubleClick} />
// Invalid
<Button /> // Property 'disabled' and 'onClick' is missing
<Button disabled /> // Property 'onClick' is missing
<Button onClick /> // Property 'disabled' is missing
- required :
disabled
,onClick
- optional :
className
,onDoubleClick
Internal
function Button({ className, disabled, onClick, onDoubleClick }: ButtonProps) {
return (
<button
className={className}
disabled={disabled}
onClick={onClick}
onDoubleClick={onDoubleClick}
/>
);
}
Button.propTypes = propTypes;
className
type :string | null | undefined
disabled
type :boolean
onClick
type :((...args: any[]) => any)
onDoubleClick
type :((...args: any[]) => any) | null | undefined
with defaultProps
External
const propTypes = {
className: PropTypes.string,
disabled: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
onDoubleClick: PropTypes.func,
};
const defaultProps = {
className: 'primary',
onDoubleClick(event: React.MouseEvent<HTMLButtonElement>) {},
};
type ButtonProps = PropsType<typeof propTypes>;
// Correct
<Button disabled onClick={onClick} />
<Button className="secondary" disabled onClick={onClick} />
<Button disabled onClick={onClick} onDoubleClick={(event: React.MouseEvent<HTMLButtonElement>) => {}} />
<Button className="secondary" disabled onClick={onClick} onDoubleClick={(event: React.MouseEvent<HTMLButtonElement>) => {}} />
// Invalid
<Button /> // Property 'disabled' and 'onClick' is missing
<Button disabled /> // Property 'onClick' is missing
<Button onClick={onClick} /> // Property 'disabled' is missing
<Button disabled onClick={onClick} onDoubleClick={(a: number) => {}} /> // Type '(a: number) => void' is not assignable to type '(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void'
- required :
disabled
,onClick
- optional :
className
,onDoubleClick
Internal
function Button({ className, disabled, onClick, onDoubleClick }: ButtonProps) {
return (
<button
className={className}
disabled={disabled}
onClick={onClick}
onDoubleClick={onDoubleClick}
/>
);
}
Button.propTypes = propTypes;
Button.defaultProps = defaultProps;
className
type :string
disabled
type :boolean
onClick
type :((...args: any[]) => any)
onDoubleClick
type :(event: React.MouseEvent<HTMLButtonElement>) => void
null
or undefined
in defaultProps
External
const propTypes = {
className: PropTypes.string,
testId: PropTypes.string,
};
const defaultProps = {
className: null,
testId: undefined,
};
type ButtonProps = PropsType<typeof propTypes, typeof defaultProps>;
// Correct
<Button />
<Button className={null} />
<Button testId={undefined} />
// Incorrect
<Button className={undefined} />
<Button testId={null} />
- required : N/A
- optional :
className
,testId
Internal
function Button({ className, testId }: ButtonProps) {
return <button className={className} data-testid={testId} />;
}
Button.propTypes = propTypes;
Button.defaultProps = defaultProps;
className
type :string | null
testId
type :string | undefined
Limits
The prop type of oneOf
in prop-types
is not inferenced to union type.
const propTypes = {
type: PropTypes.oneOf(['button', 'submit', 'reset']),
};
const defaultProps = {
type: 'button',
};
type ButtonProps = PropsType<typeof propTypes, typeof defaultProps>;
function Button({ type }: ButtonProps) {
return <button type={type}>Button</button>; // Type 'string | null | undefined' is not assignable to type '"button" | "submit" | "reset" | undefined'.
}
Button.propTypes = propTypes;
Button.defaultProps = defaultProps;
type
prop is inferenced to string
(not a 'button' | 'submit' | 'reset'
union type) because prop-types
typescript type declaration currently have problems related to InferProps
type (in @types/prop-types
). If you want to inference oneOf
as union type, this workaround can help you.
type ButtonProps = PropsType<typeof propTypes, typeof defaultProps> & {
type: 'button' | 'submit' | 'reset';
};
Thanks
This package is inspired by Brie Bunge in Adopting TypeScript at Scale, JSConf Hawaii 2019
License
MIT © Taehwan Noh