- Typing Component Props
- Basic Prop Types Examples
- object as the non-primitive type
- Empty interface, <> and Object
- Useful React Prop Type Examples
- Types or Interfaces?
- TL;DR
- More Advice
- Useful table for Types vs Interfaces
- Mastering Array Props in React with TypeScript: A Complete Guide
- Defining Props in React using TypeScript
- Working with Array Props in TypeScript
- Using PropTypes in TypeScript
- Passing Complex Props in React using TypeScript
- Other code examples for React array props using TypeScript
- Conclusion
Typing Component Props
This is intended as a basic orientation and reference for React developers familiarizing with TypeScript.
Basic Prop Types Examples
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! */ names: string[]; /** string literals to specify exact string values, with a union type to join them together */ status: "waiting" | "success"; /** an object with known properties (but could have more at runtime) */ obj: id: string; title: string; >; /** array of objects! (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: Recordstring, MyTypeHere>; // equivalent to dict1 /** function that doesn't take or return anything (VERY COMMON) */ onClick: () => void; /** function with named prop (VERY COMMON) */ onChange: (id: number) => void; /** function type syntax that takes an event (VERY COMMON) */ onChange: (event: React.ChangeEventHTMLInputElement>) => void; /** alternative function type syntax that takes an event (VERY COMMON) */ onClick(event: React.MouseEventHTMLButtonElement>): void; /** any function as long as you don't invoke it (not recommended) */ onSomething: Function; /** an optional prop (VERY COMMON!) */ optional?: OptionalType; /** when passing down the state setter function returned by `useState` to a child component. `number` is an example, swap out with whatever the type of your state */ setState: React.DispatchReact.SetStateActionnumber>>; >;
object as the non-primitive type
object is a common source of misunderstanding in TypeScript. It does not mean «any object» but rather «any non-primitive type», which means it represents anything that is not number , string , boolean , symbol , null or undefined .
Typing «any non-primitive value» is most likely not something that you should do much in React, which means you will probably not use object much.
Empty interface, <> and Object
An empty interface, <> and Object all represent «any non-nullish value»—not «an empty object» as you might think. Using these types is a common source of misunderstanding and is not recommended.
interface AnyNonNullishValue > // equivalent to `type AnyNonNullishValue = <>` or `type AnyNonNullishValue = Object` let value: AnyNonNullishValue; // these are all fine, but might not be expected value = 1; value = "foo"; value = () => alert("foo"); value = >; value = foo: "bar" >; // these are errors value = undefined; value = null;
Useful React Prop Type Examples
Relevant for components that accept other React components as props.
export declare interface AppProps children?: React.ReactNode; // best, accepts everything React can render childrenElement: JSX.Element; // A single React element style?: React.CSSProperties; // to pass through style props onChange?: React.FormEventHandlerHTMLInputElement>; // form events! the generic parameter is the type of event.target // more info: https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase/#wrappingmirroring props: Props & React.ComponentPropsWithoutRef"button">; // to impersonate all the props of a button element and explicitly not forwarding its ref props2: Props & React.ComponentPropsWithRefMyButtonWithForwardRef>; // to impersonate all the props of MyButtonForwardedRef and explicitly forwarding its ref >
Before the React 18 type updates, this code typechecked but had a runtime error:
type Props = children?: React.ReactNode; >; function Comp( children >: Props) return div>children>div>; > function App() // Before React 18: Runtime error "Objects are not valid as a React child" // After React 18: Typecheck error "Type '<>' is not assignable to type 'ReactNode'" return Comp>>>Comp>; >
This is because ReactNode includes ReactFragment which allowed type <> before React 18.
Quote @ferdaber: A more technical explanation is that a valid React node is not the same thing as what is returned by React.createElement . Regardless of what a component ends up rendering, React.createElement always returns an object, which is the JSX.Element interface, but React.ReactNode is the set of all possible return values of a component.
- JSX.Element -> Return value of React.createElement
- React.ReactNode -> Return value of a component
Types or Interfaces?
You can use either Types or Interfaces to type Props and State, so naturally the question arises — which do you use?
TL;DR
Use Interface until You Need Type — orta.
More Advice
Here’s a helpful rule of thumb:
- always use interface for public API’s definition when authoring a library or 3rd party ambient type definitions, as this allows a consumer to extend them via declaration merging if some definitions are missing.
- consider using type for your React Component Props and State, for consistency and because it is more constrained.
You can read more about the reasoning behind this rule of thumb in Interface vs Type alias in TypeScript 2.7.
The TypeScript Handbook now also includes guidance on Differences Between Type Aliases and Interfaces.
Types are useful for union types (e.g. type MyType = TypeA | TypeB ) whereas Interfaces are better for declaring dictionary shapes and then implementing or extending them.
Useful table for Types vs Interfaces
It’s a nuanced topic, don’t get too hung up on it. Here’s a handy table:
Aspect | Type | Interface |
---|---|---|
Can describe functions | ✅ | ✅ |
Can describe constructors | ✅ | ✅ |
Can describe tuples | ✅ | ✅ |
Interfaces can extend it | ⚠️ | ✅ |
Classes can extend it | 🚫 | ✅ |
Classes can implement it ( implements ) | ⚠️ | ✅ |
Can intersect another one of its kind | ✅ | ⚠️ |
Can create a union with another one of its kind | ✅ | 🚫 |
Can be used to create mapped types | ✅ | 🚫 |
Can be mapped over with mapped types | ✅ | ✅ |
Expands in error messages and logs | ✅ | 🚫 |
Can be augmented | 🚫 | ✅ |
Can be recursive | ⚠️ | ✅ |
Mastering Array Props in React with TypeScript: A Complete Guide
Learn how to work with array props in React using TypeScript. This comprehensive guide covers everything you need to know, from defining props to passing complex props. Improve your React development today!
React is a popular JavaScript library used for building user interfaces. It has gained popularity due to its ability to create reusable components, which can be used to build complex UIs. TypeScript is a typed superset of JavaScript that can be used to add type safety to React development. TypeScript helps in identifying errors at compile-time instead of runtime, leading to fewer bugs and better code quality.
In this post, we will explore how to work with array props in React using TypeScript. We will cover key points, important points, and helpful points to provide a complete guide to working with array props.
Defining Props in React using TypeScript
To define props in React, create an interface or type that describes the expected structure of the props. TypeScript helps in identifying the expected data type of the props. Destructured variables infer their type from their object. Props can be of any data type, but the expected data type for components can differ.
In the above example, we have created an interface for props with three properties: name, age, and email. The name property is of type string, and the age property is of type number. The email property is also of type string.
Working with Array Props in TypeScript
To work with an array of objects as props in TypeScript, define a type or interface for the array and pass it as a prop. Arrays can hold mixed value types, but strongly-typed arrays can be created by defining a type or interface for the array. Creating strongly-typed arrays in React and TypeScript can help ensure type safety and avoid runtime errors.
interface User < name: string; age: number; email: string; >interface Props
In the above example, we have created an interface for the user object and defined an array of users as a prop. The users prop is an array of objects, and each object has three properties: name, age, and email.
Using PropTypes in TypeScript
PropTypes can be used to define the types of props expected in a component and whether they are required or optional. PropTypes are a way to validate the props that are passed to a component. The @types/prop-types package can be used to create type definitions in TypeScript.
import PropTypes, < InferProps >from "prop-types";interface User < name: string; age: number; email: string; >const propTypes = < users: PropTypes.arrayOf( PropTypes.exact(< name: PropTypes.string.isRequired, age: PropTypes.number.isRequired, email: PropTypes.string.isRequired, >) ).isRequired, >;type Props = InferProps;
In the above example, we have created a PropTypes validation for the users prop. The users prop is an array of objects, and each object must have three properties: name, age, and email. The InferProps type is used to infer the type of the props from the PropTypes validation.
Passing Complex Props in React using TypeScript
To pass an array as a prop in TypeScript, create a type or interface for the array and pass it as a prop. Children components in React with TypeScript often require defined types. Best practices for defining and passing props in React components using TypeScript can help avoid common issues and ensure type safety.
In the above example, we have created a component that accepts an array of user objects as a prop. The UserList component maps over the user array and renders the name, age, and email properties of each user.
Other code examples for React array props using TypeScript
interface Props < propWhichIsArray: < id: ID; // I assume ID is defined elsewhere text: string; >[] >const Component: React.FC = (< propWhichIsArray >) =>
In Typescript , in particular, react array props typescript type code sample
interface Props < propWhichIsArray: < id: ID; // I assume ID is defined elsewhere text: string; >[] >const Component: React.FC = (< propWhichIsArray >) =>
Conclusion
Working with array props in React using TypeScript can help ensure type safety and avoid runtime errors. By defining types or interfaces for arrays, using PropTypes, and following best practices for passing complex props, developers can create robust and reliable React components. TypeScript offers many advantages for React development, and using it to work with array props can help make development more efficient and enjoyable.
React + TypeScript: Working with Props and Types of Props
This article covers the fundamentals of props and types of props in React and TypeScript. Without any further ado (like talking about the history of React or the benefits of using TypeScript), let’s get started.
Overview
Declaring Type of Props
You can use type or interface when defining types. Here’s a quick example:
props.children
props.children is a special property of React components used to display whatever you include between the opening and closing tags when invoking a component. In this case, the best type of props.children is React.ReactNode. The type of props.children can also be React.ReactChild, React.ReactChild[], JSX.Element[], JSX.Element, but these types have some flaws, for example, JSX.Element[] doesn’t accept strings.
A Complete Example
Preview
The sample app we are going to build has 3 functional components: App, Wrapper, and User:
- App: The root component. User data, including id, email, age, role, skills, and a function called doSomething will be passed from here.
- Wrapper: This component determines the layout and style.
- User: This component displays detailed information about a user.
Writing Code
1. Initialize a new React TypeScript project:
npx create-react-app kindacode_ts_react --template typescript
2. Create 2 new files named User.tsx and Wrapper.tsx in the src folder.
3. Add the following to Wrapper.tsx:
// Wrapper.tsx import React from "react"; interface WrapperProps < children: React.ReactNode; >const Wrapper = (< children >: WrapperProps) => < return ( > > ); >; export default Wrapper;
4. Add the following to User.tsx:
5. Replace all of the default code in App.tsx with this:
// App.tsx import React from "react"; import User, < Role >from "./User"; const user = < id: "u1", email: "[email protected]", age: 34, isMarried: false, role: Role.member, skills: ["React", "Node.js", "MySQL"], doSomething: () => < console.log(`Hello $`); >, >; const App = () => < return ( ); >; export default App;
6. Run your project and navigate to http://localhost:3000 to check the result.
Conclusion
We’ve gone through a complete example that focuses on props and types of props. If you’d like to explore more about modern React and TypeScript, take a look at the following articles:
You can also check our React category page and React Native category page for the latest tutorials and examples.