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 () => void is generally safer.

typescript-eslint has discarded Function with the ban-types rule, emitting following message with default configuration (see also here):

The Function type 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 example click (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 Overflow
🌐
React TypeScript Cheatsheets
react-typescript-cheatsheet.netlify.app › function components
Function Components | React TypeScript Cheatsheets
These can be written as normal functions that take a props argument and return a JSX element. // Declaring type of props - see "Typing Component Props" for more examples type AppProps = { message: string; }; /* use `interface` if exporting so that consumers can extend */ // Easiest way to declare a Function Component; return type is inferred.
Top answer
1 of 2
68

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 () => void is generally safer.

typescript-eslint has discarded Function with the ban-types rule, emitting following message with default configuration (see also here):

The Function type 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 example click (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

2 of 2
10

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.

Discussions

reactjs - Add typing for function component in React JS - Stack Overflow
I noticed that some of developers type react js functional component like this: const Result: React.FC { I don't understand the idea, why... More on stackoverflow.com
🌐 stackoverflow.com
reactjs - React TS function argument types - Stack Overflow
There is a HOC component for storing the value of one state for all elements as input, select. The output function accepts an arguments ({text: Component, select: Component}). While typing an argu... More on stackoverflow.com
🌐 stackoverflow.com
TypeScript React.FC<Props> confusion - javascript
For both functional components above, I see TypeScript generates the same JS code. The PrintName2 component seems more streamlined to me as far as readability. I wonder what's the difference between the two definitions and if anyone is using second type of React component? More on stackoverflow.com
🌐 stackoverflow.com
Function component props with typescript
Yes. Defining an interface separately, makes it reusable and easier to read and move. More on reddit.com
🌐 r/reactjs
18
3
January 18, 2023
🌐
React
react.dev › learn › typescript
Using TypeScript – React
Like useMemo, the function’s type is inferred from the return value of the function in the first parameter, and you can be more explicit by providing a type argument to the Hook. ... When working in TypeScript strict mode useCallback requires adding types for the parameters in your callback.
🌐
React TypeScript Cheatsheets
react-typescript-cheatsheet.netlify.app › typing component props
Typing Component Props | React TypeScript Cheatsheets
A list of TypeScript types you will likely use in a React+TypeScript app: type AppProps = { message: string; count: number; disabled: boolean; /** array of a type!
🌐
Echobind
echobind.com › post › react-with-typescript-components-as-function-declarations-vs-function-expressions
TypeScript: Function Declarations vs. Function Expressions
December 13, 2019 - In the other instance, when we type a React component as a function declaration (i.e. function MyComponent), we ask the same thing. This time, we’re annotating the function return type. This explains why we can’t use the same type! We instead need to tell TypeScript, “Hey!
🌐
GitHub
github.com › typescript-cheatsheets › react
GitHub - typescript-cheatsheets/react: Cheatsheets for experienced React developers getting started with TypeScript · GitHub
There are some tools that let you run React and TypeScript online, which can be helpful for debugging or making sharable reproductions. ... These can be written as normal functions that take a props argument and return a JSX element. // Declaring type of props - see "Typing Component Props" for more examples type AppProps = { message: string; }; /* use `interface` if exporting so that consumers can extend */ // Easiest way to declare a Function Component; return type is inferred.
Starred by 47K users
Forked by 4.3K users
Languages   JavaScript 93.9% | CSS 5.8% | Shell 0.3%
🌐
Carl Rippon
carlrippon.com › different-ways-to-strongly-type-function-component-props-with-typescript
Different ways to strongly-type function component props with TypeScript
April 7, 2020 - The FC type is used on the variable assigned to the arrow function. It is a generic type that we pass the components props type into. There are some arguable minor benefits to using the FC type: FC provides some type safety on defaultProps, which can be used to provide default values for the props. However, defaultProps may be removed from React in a future release.
Find elsewhere
Top answer
1 of 1
3

Is not enough to type the component in this way:

Yes, that's enough. You don't have to repeat the type of the props, this is just fine:

const Result: React.FC<ResultProps> = ({ prop1, prop2 }) => {
    // ...
};

Playground link

That works because you've already set the type of Result, so TypeScript knows what parameters the function accepts and their types.


A note about React.FC: In the types for React v17.x and below, when you used React.FC for your component, you were saying it supported children. Your component doesn't support children, so I thought I should call it out. Many people started saying not to use React.FC for this very reason: it was easy to accidentally give your component the wrong type information. But in React v18.x and above, they changed the definition of React.FC so that it no longer assumes your component supports children. (If you want to say it does, you add PropsWithChildren like this: React.FC<PropsWithChildren<ResultProps>>.)

So if you're using v17.x or below and you don't want the component to say it supports children when it doesn't, here's an alternative way to do the types for it that you often see:

const Result = ({ prop1, prop2 }: ResultProps) => {
    // ...
};

Playground link

Note, though, that that relies on you returning the correct thing from the component, since there's no return type annotation TypeScript can use to help you if you forget to return something or return something that isn't valid for a component (like returning a plain object). So you might include a return type as well:

const Result = ({ prop1, prop2 }: ResultProps): JSX.Element => {
    // ...
};

Playground link

But again, in the types for React v18.x, React.FC no longer assumes your component supports children.

🌐
Better Programming
betterprogramming.pub › the-right-way-to-create-function-components-in-react-with-typescript-59dcf4076b92
The Right Way to Create Function Components in React With TypeScript | by Ozan Tunca | Better Programming
August 27, 2020 - Function components essentially work the same way. They take properties and convert them into UI elements. You can see below a super-basic function component example from reactjs.org using plain JavaScript. By rewriting this component with TypeScript, we aim to make sure that we
🌐
DEV Community
dev.to › wpreble1 › typescript-with-react-functional-components-4c69
TypeScript with React Functional Components - DEV Community
July 16, 2020 - Similar to other statically-typed languages like C# or Java, it forces you to be deliberate with variable types by declaring them upon creation. In this blog, I’ll cover the basics of incorporating TypeScript into the popular front-end framework (er… library) React with a focus on functional components and hooks.
🌐
Pluralsight
pluralsight.com › tech insights & how-to guides › tech guides & tutorials
Passing Functions in React with TypeScript | Pluralsight
June 2, 2019 - As a sample reference, the ClickHandler prop function is currently set up to receive an event parameter of React.MouseEvent type that is applied to an HTMLButtonElement. Any time you click on an element in JavaScript with your mouse, it receives this event property by default. We won’t be needing it in our example. If you did need information about the mouse click event, this is how you would let TypeScript know about the type of event and the type of element that was clicked.
🌐
CodiLime
codilime.com › blog › software development › frontend › a guide to react functional components with typescript
A guide to React functional components with TypeScript
However, it's essential to note that there might be an initial learning curve if you are not familiar with TypeScript. Once you become accustomed to it, the benefits will outweigh the initial investment of time and effort. Let’s focus on typing the main building brick of any React application - the component. I assume you’re already familiar with the good old `FunctionalComponent` or `FC`. It’s a basic type provided by React.
🌐
Dmitri Pavlutin
dmitripavlutin.com › typescript-react-components
How to Use TypeScript with React Components - Dmitri Pavlutin
September 29, 2021 - In this post, I'm going to discuss why and how to use TypeScript to type React components. You'll find how to annotate component props, mark a prop optional, and indicate the return type. ... TypeScript is useful if you're coding middle and bigger size web applications. Annotating variables, objects, and functions creates contracts between different parts of your application.
🌐
Fettblog
fettblog.eu › typescript-react › components
TypeScript and React: Components
Creating a type for our properties, and telling TypeScript that the parameters of our functional component are of that type. You already get nice suggestions in VS Code: And errors when you compile without passing all required properties: If you want to make some properties optional, do that in the respective Props type: type CardProps = { title: string, paragraph?: string // the paragraph is optional } There’s a generic type you can use. import React, { FunctionComponent } from 'react'; // importing FunctionComponent type CardProps = { title: string, paragraph: string } export const Card: FunctionComponent<CardProps> = ({ title, paragraph }) => <aside> <h2>{ title }</h2> <p> { paragraph } </p> </aside> const el = <Card title="Welcome!" paragraph="To this example" />
🌐
W3Schools
w3schools.io › learn › react-typescript-functional-components
The Ultimate Guide to Building Functional Components in React Typescript - w3schools
Let’s see multiple ways to create Typescript functional components. ... Declare Normal Function with props parameters of the type above MessageProps(use type or interface). ... import React, { FC } from 'react'; interface MessageProps { message: string; } function FunctionalComponent(props:MessageProps){ return ( <> <h1>Welcome {props.message}</h1> </> ); }; export default FunctionalComponent;
🌐
Robin Wieruch
robinwieruch.de › typescript-react-component
React Component with TypeScript
From there, we would start extracting reusable types from the functional component's function signature into a standalone TypeScript type. It's up to you whether you prefer using a type or interface: ... Since React props are just a JavaScript object, we can extract a type respectively to the ...
🌐
Bobby Hadz
bobbyhadz.com › blog › react-typescript-pass-function-as-prop
How to pass Functions as Props in React TypeScript | bobbyhadz
February 29, 2024 - The example shows how to pass functions as props to a React component using TypeScript. The sum function takes 2 parameters of type number and returns a number.
Top answer
1 of 1
2

There are a number of issues with this code, but the particular error that you posted is due to declaring the type of CustomFabric as React.FC<Param> when it is not a function component.

A function component is a function which takes a single argument -- a props object -- and returns some JSX element. Your CustomFabric takes props but it returns a function. So it is inherently incompatible with the React.FC type.

I'm trying to figure out what this code is supposed to do because the typings that you have don't match how you are using it. It looks like text and select are supposed to be components, but your interface says that they are functions which take no arguments and return nothing. If they are components then they should use the React.ComponentType<Props> type.

I also fundamentally don't "get" what the point is of having a controlled input where the state is behind a black box where you can't access it. CustomFabric doesn't seem to give you any access to the state. So I don't see what goal is being accomplished here.

But we can do a better job of properly typing what you have here, which is a function that return a hook. This code fixes most of your issues by declaring that:

  • text and select are components which take props value and onChange
  • CustomFabric will be called with an object containing components for text and select
  • CustomFabric returns a function which takes a name and returns a component. That name must be either 'text' or 'select' and the returned component does not require any props.

There is still a lot of room for improvement. For example your code passes through additional props to the input and select, but these types don't allow for any props other than value and onChange. Your settings only has two properties, so you would get better type inference by dealing with those keys directly rather than looping through Object.entries.

type InputComponent = React.ComponentType<{value: string, onChange: React.ChangeEventHandler}>;

interface PropsTypes {
  text: InputComponent;
  select: InputComponent;
}

export const CustomFabric = (settings: PropsTypes) => {
  const elements = Object.entries(settings) as [keyof PropsTypes, InputComponent][];
  const newSettings = elements.reduce((acc, item) => {
    const key = item[0];
    const Component = item[1];

    acc[key] = (props: any) => {
      const [value, setValue] = useState('');
      const onChange = (event: { target: { value: any } }) => {
        setValue(event.target.value);
      };
      return <Component value={value} onChange={onChange} {...props} />;
    };

    return acc;
  }, {} as Record<keyof PropsTypes, React.FC>);

  return (type: keyof PropsTypes): React.FC => {
    return newSettings[type];
  };
};

Typescript Playground Link

Top answer
1 of 5
217

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.FC syntax is slightly more verbose without providing clear advantage, so precedence was given to the "normal function" syntax.

2 of 5
93

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:

  1. Provides an implicit definition of children, even if your component doesn't need to have children. That might cause an error.
  2. Doesn't support generics.
  3. Doesn't work correctly with defaultProps.