Concerning Function and best practices
Function in practice has unsufficient type-safety, being the super-type of all functions. You better replace it with a function type - see the "Solutions" section down under.
In above example, Function is not assignable to the more narrow onClick function type, which causes the error at hand (Playground example).
In addition to mentioned issue, here is what TypeScript docs say about Function:
This is an untyped function call and is generally best avoided because of the unsafe any return type. If need to accept an arbitrary function but don’t intend to call it, the type
() => voidis generally safer.
typescript-eslint has discarded Function with the ban-types rule, emitting following message with default configuration (see also here):
The
Functiontype accepts any function-like value. It provides no type safety when calling the function, which can be a common source of bugs. If you are expecting the function to accept certain arguments, you should explicitly define the function shape.
Better solutions
React already comes with built-in event handler-types to handle common events.
For exampleclick (Playground):
type Props = {
onClick: React.MouseEventHandler<HTMLButtonElement>
};
const Submit = ({ onClick }: Props) => <button onClick={onClick}> click </button>
A more general alternative is to use function types as follows:
type Props = {
onClick: (event: React.MouseEvent<HTMLElement>) => void
};
void is more restrictive than any. There is no chance to return a value in the callback by accident, which would be possible with any.
In summary, we embrace typing capabilities of TypeScript instead of using Function or any.
The parameter now is known to be MouseEvent and the return type void, identifying it as a callback.
Related
Typescript: How to define type for a function callback (as any function type, not universal any) used in a method parameter
Answer from ford04 on Stack OverflowConcerning Function and best practices
Function in practice has unsufficient type-safety, being the super-type of all functions. You better replace it with a function type - see the "Solutions" section down under.
In above example, Function is not assignable to the more narrow onClick function type, which causes the error at hand (Playground example).
In addition to mentioned issue, here is what TypeScript docs say about Function:
This is an untyped function call and is generally best avoided because of the unsafe any return type. If need to accept an arbitrary function but don’t intend to call it, the type
() => voidis generally safer.
typescript-eslint has discarded Function with the ban-types rule, emitting following message with default configuration (see also here):
The
Functiontype accepts any function-like value. It provides no type safety when calling the function, which can be a common source of bugs. If you are expecting the function to accept certain arguments, you should explicitly define the function shape.
Better solutions
React already comes with built-in event handler-types to handle common events.
For exampleclick (Playground):
type Props = {
onClick: React.MouseEventHandler<HTMLButtonElement>
};
const Submit = ({ onClick }: Props) => <button onClick={onClick}> click </button>
A more general alternative is to use function types as follows:
type Props = {
onClick: (event: React.MouseEvent<HTMLElement>) => void
};
void is more restrictive than any. There is no chance to return a value in the callback by accident, which would be possible with any.
In summary, we embrace typing capabilities of TypeScript instead of using Function or any.
The parameter now is known to be MouseEvent and the return type void, identifying it as a callback.
Related
Typescript: How to define type for a function callback (as any function type, not universal any) used in a method parameter
You can simply write it like this, which prevents any and is more telling. Especially for custom functions:
Interface Props { onClick: (e: Event) => void; }
This will tell the calling component, what onClick will expect and what the parameters are.
Hope this helps. Happy coding.
reactjs - Add typing for function component in React JS - Stack Overflow
reactjs - React TS function argument types - Stack Overflow
TypeScript React.FC<Props> confusion - javascript
Function component props with typescript
Videos
Thanks all for the answers. They are correct but I was looking for a more detailed version. I did some more research and found this on React+TypeScript Cheatsheets on GitHub.
Function Components
These can be written as normal functions that take a props argument and return a JSX element.
type AppProps = { message: string }; /* could also use interface */
const App = ({ message }: AppProps) => <div>{message}</div>;
What about React.FC/React.FunctionComponent?
You can also write components with React.FunctionComponent (or the shorthand React.FC):
const App: React.FC<{ message: string }> = ({ message }) => (
<div>{message}</div>
);
Some differences from the "normal function" version:
It provides typechecking and autocomplete for static properties like displayName, propTypes, and defaultProps - However, there are currently known issues using defaultProps with React.FunctionComponent. See this issue for details - scroll down to our defaultProps section for typing recommendations there.
It provides an implicit definition of children (see below) - however there are some issues with the implicit children type (e.g. DefinitelyTyped#33006), and it might be considered a better style to be explicit about components that consume children, anyway.
const Title: React.FunctionComponent<{ title: string }> = ({
children,
title
}) => <div title={title}>{children}</div>;
In the future, it may automatically mark props as readonly, though that's a moot point if the props object is destructured in the parameter list.
React.FunctionComponent is explicit about the return type, while the normal function version is implicit (or else needs additional annotation).
In most cases, it makes very little difference which syntax is used, but the
React.FCsyntax is slightly more verbose without providing clear advantage, so precedence was given to the "normal function" syntax.
React.FC is not the preferable way to type a React component, here's a link.
I personally use this type:
const Component1 = ({ prop1, prop2 }): JSX.Element => { /*...*/ }
Short list of React.FC cons:
- Provides an implicit definition of children, even if your component doesn't need to have children. That might cause an error.
- Doesn't support generics.
- Doesn't work correctly with
defaultProps.