props-type
TypeScript icon, indicating that this package has built-in type declarations

1.0.1 • Public • Published

props-type npm version github actions

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

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 is disabled: 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 is boolean
  • External : <Button disabled?: boolean | undefined />

Required (with isRequired)

without defaultProps

const propTypes = { disabled: PropTypes.bool.isRequired };
type Props = PropsType<typeof propTypes>;
  • Internal : Props type is disabled: 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 is disabled: 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

Package Sidebar

Install

npm i props-type

Weekly Downloads

469

Version

1.0.1

License

MIT

Unpacked Size

11.8 kB

Total Files

8

Last publish

Collaborators

  • taehwanno