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 โ€บ typing component props
Typing Component Props | React TypeScript Cheatsheets
(common) */ objArr: { id: string; title: string; }[]; /** any non-primitive value - can't access any properties (NOT COMMON but useful as placeholder) */ obj2: object; /** an interface with no required properties - (NOT COMMON, except for things like `React.Component<{}, State>`) */ obj3: {}; /** a dict object with any number of properties of the same type */ dict1: { [key: string]: MyTypeHere; }; dict2: Record<string, MyTypeHere>; // equivalent to dict1 /** function that doesn't take or return anything (VERY COMMON) */ onClick: () => void; /** function with named prop (VERY COMMON) */ onChang
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

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
How to pass function as a prop in react typescript
I am learning typescript with react and I occurred problem. I tried to pass function as a prop from my App component to child component named DataForm. but I got an error: Type '(f: any) => any... More on stackoverflow.com
๐ŸŒ stackoverflow.com
reactjs - how to set prop type in react + typescript - Stack Overflow
i studied react + typescript. i want to set component function prop type. but i don't know how to set. this is code. interface MovieProps { id: number; title: string; year: number; } More on stackoverflow.com
๐ŸŒ stackoverflow.com
Callback props and Typescript - inline allow TypeScript to infer the parameters, or make explicit?
for simple shit sure do #1 but #2 is literally just a waste of time. #3 is how you do it for readability More on reddit.com
๐ŸŒ r/reactjs
33
5
September 13, 2023
๐ŸŒ
Pluralsight
pluralsight.com โ€บ tech insights & how-to guides โ€บ tech guides & tutorials
Defining Props in React Function Component with Typescript | Pluralsight
But what if you want to define default function component props if they aren't passed in? Or you just want to have cleaner syntax within your component? For those cases, you can leverage a JavaScript syntax feature known as destructuring. This allows more flexibility in how you can define your props. // Using the same FullName interface from the last example function FunctionalComponent({firstName, lastName}:FullName){ // firstName // lastName }
๐ŸŒ
Oida
oida.dev โ€บ typescript-react โ€บ prop-types
TypeScript and React: Prop Types
July 17, 2019 - import PropTypes, { InferProps } from "prop-types"; export function Article({ title, price }: InferProps<typeof Article.propTypes>) { return ( <div className="article"> <h1>{title}</h1> <span>Priced at (incl VAT): {price * 1.2}</span> </div> ); } Article.propTypes = { title: PropTypes.string.isRequired, price: PropTypes.number.isRequired };
๐ŸŒ
Ben Ilegbodu
benmvp.com โ€บ blog โ€บ react-prop-types-with-typescript
React Prop Types with TypeScript | Ben Ilegbodu
NOTE: PropTypes.shape() allows for additional properties outside of those to be included in the object, so technically the equivalent TypeScript type is an index type. But generally, when folks use PropTypes.shape() they really mean PropTypes.exact(). Prop types: Example.propTypes = { onClick: PropTypes.func, onChange: PropTypes.func, onSelect: PropTypes.func, } TypeScript: interface Props { onClick: () => void onChange: (val: string) => void onSelect: (id: string, val: number) => void } NOTE: As you can see, function prop types do not define their interface, while TypeScript functions have an explicit definition of their params and return value.
Find elsewhere
๐ŸŒ
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.
๐ŸŒ
Akos Komuves
akoskm.com โ€บ how-to-type-react-props-with-typescript
How to type React Props with TypeScript | Akos Komuves
January 6, 2023 - It is a shorthand for describing a functional component that has a prop type. In our example, ProfileCard is a functional component that expects to receive props with a name string and an age number.
๐ŸŒ
DEV Community
dev.to โ€บ anavalo โ€บ enforcing-prop-combinations-with-typescript-function-overloading-in-react-4ob2
Conditional React props with TypeScript Function Overloading - DEV Community
October 20, 2023 - The component should only accept an icon prop if a handleClickIcon function is also present. ... This won't enforce that handleClickIcon is relevant only when you've got an icon. A better strategy is to use function overloading in TypeScript: type CommonProps = { text: string }; type IconAndClickProps = { icon: JSX.Element; handleClickIcon: () => void }; // function overloading export function Button(props: CommonProps): JSX.Element; export function Button(props: CommonProps & IconAndClickProps): JSX.Element; export function Button(props: CommonProps & IconAndClickProps): JSX.Element { // ...your button implementation }
๐ŸŒ
Steve Kinney
stevekinney.com โ€บ courses โ€บ react with typescript โ€บ complete guide to react component props with typescript
Complete Guide to React Component Props with TypeScript | React with TypeScript | Steve Kinney
3 weeks ago - type ButtonProps = { children: React.ReactNode; } & ( | { variant: 'button'; onClick: () => void; disabled?: boolean; } | { variant: 'link'; href: string; target?: '_blank' | '_self'; } | { variant: 'submit'; form?: string; disabled?: boolean; } ); function Button(props: ButtonProps) { const { children } = props; switch (props.variant) { case 'button': return ( <button onClick={props.onClick} disabled={props.disabled}> {children} </button> ); case 'link': return ( <a href={props.href} target={props.target}> {children} </a> ); case 'submit': return ( <button type="submit" form={props.form} disabled={props.disabled}> {children} </button> ); } } // TypeScript ensures correct prop combinations <Button variant="button" onClick={() => {}}>Click</Button> <Button variant="link" href="/home">Home</Button> <Button variant="submit" form="myForm">Submit</Button>
๐ŸŒ
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 - In the above example, we have extended the standard props type for an input element. This means our component now accepts props such as maxLength and placeholder. Alternatively we can use a type alias and intersection to achieve the same effect: ... A comprehensive guide to building modern React applications with TypeScript...
๐ŸŒ
DEV Community
dev.to โ€บ captainyossarian โ€บ how-to-type-react-props-as-a-pro-2df2
How to type React props as a pro in TypeScript - DEV Community
July 25, 2021 - So, lets merge our function union with less specific overload ยท // credits goes to https://stackoverflow.com/a/50375286 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ( k: infer I ) => void ? I : never; type Overload<PropsUnion> = & UnionToIntersection<PropsUnion[FnProps<PropsUnion>]> & ParametersUnion<PropsUnion> // & ((a: A['data']) => string) // & ((a: B['data']) => number) // & ((a: C['data']) => number) // & ((a: string | number | number[]) => string | number) type Result3 = Overload<Props>
๐ŸŒ
amanhimself.dev
amanhimself.dev โ€บ blog โ€บ prop-types-in-react-and-typescript
Prop types in React and TypeScript | amanhimself.dev
June 28, 2021 - TypeScript is smart enough not to compile the code if a prop has a type of any. PropTypes package offers InferProps that enables to infer the types for an existing prop-type definition on a component. It uses the @types/prop-types package to create type definitions. To use InferProps, import it from the prop-types library and then define type declarations on the components prop. import PropTypes, { InferProps } from 'prop-types'; function FavoriteColor({ color }: InferProps<typeof FavoriteColor.propTypes>) { return <h2>My favorite Color is </h2>; } FavoriteColor.propTypes = { color: PropTypes.string };
๐ŸŒ
DEV Community
dev.to โ€บ lico โ€บ react-ts-dont-repeat-the-type-when-you-pass-functions-as-props-use-their-types-5h6h
React TS: Don't repeat the type when you pass functions as props, use their types. - DEV Community
August 21, 2022 - Don't repeat the type when you pass functions as props, use their types. Let's suppose, there is a... Tagged with react, typescript, webdev, beginners.
๐ŸŒ
React TypeScript Cheatsheets
react-typescript-cheatsheet.netlify.app โ€บ function components
Function Components | React TypeScript Cheatsheets
// 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.
๐ŸŒ
React
legacy.reactjs.org โ€บ docs โ€บ typechecking-with-proptypes.html
Typechecking With PropTypes โ€“ React
This uses // JS's instanceof operator. optionalMessage: PropTypes.instanceOf(Message), // You can ensure that your prop is limited to specific values by treating // it as an enum. optionalEnum: PropTypes.oneOf(['News', 'Photos']), // An object that could be one of many types optionalUnion: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.instanceOf(Message) ]), // An array of a certain type optionalArrayOf: PropTypes.arrayOf(PropTypes.number), // An object with property values of a certain type optionalObjectOf: PropTypes.objectOf(PropTypes.number), // An object taking on a
๐ŸŒ
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 ...