-
Notifications
You must be signed in to change notification settings - Fork 357
TypeScript Conversion Guide
Converting a component to TypeScript has multiple steps. There's a helper script react-core/scripts/convertComponentToTS.js
to help with the tedious parts. Backup the JS for a component and then run node scripts/convertComponentToTS.js src/components/Alert
and pull up the TSX/JS side-by-side to begin.
Converting a class has a lot of caveats.
When converting PatternFly components to TypeScript, you'll need to specify a type for the interface as follows:
export interface LabelProps {
children: React.ReactNode;
className?: string;
isCompact?: boolean;
}
Oftentimes we spread props to an HTML element like <div {...props}>
. In that case have the props extend types in node_modules/typescript/lib/lib.dom.d.ts
like so:
export interface LabelProps extends React.HTMLProps<HTMLDivElement> ...
In some cases, you will need to avoid duplicating a type specified in HTMLWhateverElement
. You can use Omit
for this purpose. In the example below, size
is omitted from the inherited type HTMLHeadingElement
so we can use our own type for it.
export interface TitleProps extends Omit<React.HTMLProps<HTMLHeadingElement>, 'size'> {
/** the size of the Title */
size: keyof typeof BaseSizes;
/** content rendered inside the Title */
children?: React.ReactNode;
/** Additional classes added to the Title */
className?: string;
/** the heading level to use */
headingLevel?: TitleLevel;
}
HTMLImageElement
's types are shot for some reason, so for now use extends React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>
.
Use the static
attribute as follows:
export class Wizard extends React.Component<WizardProps, WizardState> {
static defaultProps = {
hasBodyPadding: true,
...
};
These components are pretty easy to convert.
export const WizardBody: React.FunctionComponent<WizardBodyProps> = ({
children,
hasBodyPadding = true
}: WizardBodyProps) => {
<main>
{children}
</main>
);
When a property can have only one of a specified set of string values, we will define a enum with each of the possible values as the keys and values. export enum and type out the strings in the prop type definition
export enum OptionsMenuDirection {
up = 'up',
down = 'down'
};
export interface OptionsMenuProps extends React.HTMLProps<HTMLDivElement>{
//prop type declarations
direction?: 'up' | 'down';
}
We will try to use ReactNode as a type rather than ReactElement or ReactType (which is deprecated anyway) for relevant props unless there is a specific reason why you cannot.
Both of these are required for the build to pass. Run yarn typecheck
in react-core to typecheck your component. Run yarn lint:ts
to lint your TS files. These results aren't always the same as what VSCode natively says, we need to find a way to share our tsconfig.typecheck.json and tslint.json with VSCode :)
We can't test that our types work as expected for consumers without integration tests. When you convert a component, add a demo to react-integration
and that's all (for now...)