TypeScript CookBook
Properly type React Children
In your functional component, use React.FC<Props>
as function type and children
will be implicitly accounted for in your Props
, without needing to explicitly type them.
import React, { ReactElement } from 'react';
interface OwnProps {
title: string
}
const Example: React.FC<OwnProps> = (props): ReactElement => {
return (
<div>
<header>{props.title}</header>
<main>
{props.children}
</main>
</div>
);
}
export default Example;
Type a function in props
interface OwnProps {
// shorthand
clickHandler(e: React.MouseEvent): void;
// longhand
changeHandler: (e: React.ChangeEvent) => void
}
Notice the shorthand notation.
Type an event handler's event
param
interface OwnProps {
clickHandler(e: React.MouseEvent): void;
}
const example: React.FC<OwnProps> = ({ clickHandler }): ReactElement => {
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
clickHandler?.(e);
}
return <button onClick={handleClick}>Click</button>;
};
export default example;
Don't use regular DOM events, but events under the React
namespace, such as React.MouseEvent
. Also provide an argument to the generic, specifying the type of element the handler is attached to.
Type a ref
const example: React.FC<OwnProps> = (): ReactElement => {
const ref = useRef<HTMLDivElement>(null);
return <div ref={ref} />;
};
Provide the type of the target element to the ref.
Type a library which doesn't come with its own types
In a type definition file (filename must follow the convention file.d.ts
), write:
declare module 'lib-name';
This way TS will register the lib in the type system and (hopefully) turn off any errors.
Type a class component
interface props {}
export default class Example extends Component<Props> { // ... }
Null types
Null types are automatically accounted for by TS in our type declarations (unless the strictNullChecks
config option is active); null
and undefined
are assignable to every type.
// TS sees: x: string | null | undefined
var x: string = 'x';
// no TS errors
x = null;
x = undefined;
Create a class based on an interface
interface Xyz {
x: string;
}
class Example implements Xyz {
x: string
// ...
}
Classes and access levels
- public: the default; access from the instance (dot notation from instantiated object) and from subclasses;
- private: access restricted to the class scope; no access from the instance & neither from subclasses
- protected: like private, but with access from subclasses
- static: access directly from the class, without instantiating. (i.e.
Math.PI
)
Access level | subclass access | instance access ---------------- | --------------------- | --------------------- private | X | X protected | √ | X static | √ | X public | √ | √
Note: by setting a constructor as protected, we can prevent the class from being instanciated.
Reference
- www.typescriptlang.org/
- TutsPlus TypeScript series: