In React with TypeScript, components can be given type information for their props, state, functions, children, and other values. This makes reusable components easier to understand and maintain.
.tsx files when using TypeScript.
A React component is a reusable piece of UI. It can return JSX that describes what should appear on the screen.
function Welcome() {
return <h1>Welcome</h1>;
}
Function components are JavaScript or TypeScript functions that return JSX.
function App() {
return (
<div>
<h1>My App</h1>
</div>
);
}
TypeScript can add types to the data used by a React component.
function Welcome(): JSX.Element {
return <h1>Welcome</h1>;
}
The component returns JSX.
Props are values passed from a parent component to a child component.
function Student(props: { name: string }) {
return <h2>{props.name}</h2>;
}
An interface can describe the props expected by a component.
interface StudentProps {
name: string;
age: number;
}
function Student(props: StudentProps) {
return (
<div>
<h2>{props.name}</h2>
<p>Age: {props.age}</p>
</div>
);
}
Props can be destructured directly in the function parameter.
interface StudentProps {
name: string;
age: number;
}
function Student({
name,
age
}: StudentProps) {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}
<Student
name="Rahul"
age={20}
/>
TypeScript checks whether the supplied values match the defined prop types.
A prop without ? is required.
interface UserProps {
name: string;
age: number;
}
Both name and age must be supplied.
Add ? to make a prop optional.
interface UserProps {
name: string;
age?: number;
}
Now age can be omitted.
interface UserProps {
name: string;
age?: number;
}
function User({
name,
age = 18
}: UserProps) {
return (
<p>
{name} - {age}
</p>
);
}
interface MessageProps {
message: string;
}
function Message({
message
}: MessageProps) {
return <p>{message}</p>;
}
interface ProductProps {
price: number;
}
function Product({
price
}: ProductProps) {
return <p>Price: ₹{price}</p>;
}
interface ButtonProps {
disabled: boolean;
}
function Button({
disabled
}: ButtonProps) {
return (
<button disabled={disabled}>
Submit
</button>
);
}
interface ListProps {
students: string[];
}
function StudentList({
students
}: ListProps) {
return (
<ul>
{students.map((student) =>
<li key={student}>
{student}
</li>
)}
</ul>
);
}
interface Student {
id: number;
name: string;
}
interface StudentProps {
student: Student;
}
function StudentCard({
student
}: StudentProps) {
return (
<div>
<h2>{student.name}</h2>
<p>ID: {student.id}</p>
</div>
);
}
A function can also be passed as a prop.
interface ButtonProps {
onClick: () => void;
}
function MyButton({
onClick
}: ButtonProps) {
return (
<button onClick={onClick}>
Click Me
</button>
);
}
interface UserProps {
onSelect: (id: number) => void;
}
function UserButton({
onSelect
}: UserProps) {
return (
<button onClick={() => onSelect(101)}>
Select User
</button>
);
}
A component can receive nested content using the
children prop.
import { ReactNode } from "react";
interface CardProps {
children: ReactNode;
}
function Card({
children
}: CardProps) {
return (
<div>
{children}
</div>
);
}
<Card>
<h2>Student Details</h2>
<p>Welcome to the course.</p>
</Card>
The nested JSX is received through the
children prop.
A React component can explicitly specify an appropriate return type.
function Welcome(): JSX.Element {
return <h1>Welcome</h1>;
}
In many projects, TypeScript can also infer the component's return type automatically.
import React from "react";
const Welcome: React.FC = () => {
return <h1>Welcome</h1>;
};
React.FC is one way to type a function
component. Explicitly typing props is also common.
interface UserProps {
name: string;
}
const User: React.FC<UserProps> = ({
name
}) => {
return <h2>{name}</h2>;
};
import { useState } from "react";
interface User {
name: string;
age: number;
}
function UserProfile() {
const [user, setUser] =
useState<User>({
name: "Rahul",
age: 20
});
return (
<div>
<h2>{user.name}</h2>
<p>{user.age}</p>
</div>
);
}
interface ProductProps {
name: string;
price: number;
available: boolean;
}
function Product({
name,
price,
available
}: ProductProps) {
return (
<div>
<h2>{name}</h2>
<p>Price: ₹{price}</p>
<p>
{available
? "Available"
: "Not Available"}
</p>
</div>
);
}
interface ButtonProps {
text: string;
onClick: () => void;
disabled?: boolean;
}
function Button({
text,
onClick,
disabled = false
}: ButtonProps) {
return (
<button
onClick={onClick}
disabled={disabled}
>
{text}
</button>
);
}
interface ButtonProps {
onClick: (
event: React.MouseEvent<HTMLButtonElement>
) => void;
}
function Button({
onClick
}: ButtonProps) {
return (
<button onClick={onClick}>
Click
</button>
);
}
interface Student {
id: number;
name: string;
course: string;
}
interface StudentCardProps {
student: Student;
}
function StudentCard({
student
}: StudentCardProps) {
return (
<div>
<h2>{student.name}</h2>
<p>ID: {student.id}</p>
<p>Course: {student.course}</p>
</div>
);
}
interface Student {
name: string;
course: string;
}
interface StudentListProps {
students: Student[];
}
function StudentList({
students
}: StudentListProps) {
return (
<div>
{students.map((student) => (
<StudentCard
key={student.name}
student={student}
/>
))}
</div>
);
}
? when a prop is optional.import { useState } from "react";
interface Student {
id: number;
name: string;
course: string;
}
interface StudentCardProps {
student: Student;
onSelect: (id: number) => void;
}
function StudentCard({
student,
onSelect
}: StudentCardProps) {
return (
<div>
<h2>{student.name}</h2>
<p>
ID: {student.id}
</p>
<p>
Course: {student.course}
</p>
<button
onClick={() =>
onSelect(student.id)
}
>
Select Student
</button>
</div>
);
}
function App() {
const [student] = useState<Student>({
id: 101,
name: "Rahul",
course: "React Native"
});
const handleSelect = (id: number): void => {
console.log(
"Selected Student ID:",
id
);
};
return (
<div>
<h1>Student Details</h1>
<StudentCard
student={student}
onSelect={handleSelect}
/>
</div>
);
}
export default App;
This example combines typed objects, typed props, function props, state, and a reusable React component.
?.ReactNode.Question: Which TypeScript feature is commonly used to define the expected props of a React component?