React Native TypeScript
TypeScript adds a safety net to JavaScript. It lets you describe the shape of every value, and the editor warns you about mistakes before the app runs. A misspelled prop, a missing field, or a wrong data type shows up as a red underline while you type. Large teams and long-lived apps rely on this early feedback.
The Core Idea
JavaScript TypeScript ───────────────── ───────────────────────── Run app Write code Tap button Editor flags the error Crash appears Fix it right away Hunt for the cause Run app, no crash
TypeScript code compiles down to plain JavaScript. The phone never sees the types. They exist only to protect you during development.
Start a TypeScript Project
npx create-expo-app my-app --template blank-typescript
Existing projects convert step by step. Add a tsconfig.json, install the type packages, and rename files from .js to .tsx one at a time. Files with JSX use .tsx. Plain logic files use .ts.
Basic Types
const name: string = 'Asha';
const age: number = 24;
const isMember: boolean = true;
const scores: number[] = [90, 85, 70];
TypeScript guesses types from the starting value, so explicit labels are often optional. const age = 24 already counts as a number.
Describe Data with Types and Interfaces
An interface names the shape of an object. Think of it as a form template with labeled blanks.
interface Product {
id: number;
title: string;
price: number;
inStock?: boolean; // the question mark marks an optional field
}
const phone: Product = { id: 1, title: 'Phone', price: 299 };
Product ├── id : number ├── title : string ├── price : number └── inStock? : boolean (optional)
Type Component Props
Props are the inputs of a component. Describe them so callers cannot forget a value or pass the wrong kind.
import { Text, TouchableOpacity } from 'react-native';
interface PrimaryButtonProps {
label: string;
onPress: () => void;
disabled?: boolean;
}
export function PrimaryButton({ label, onPress, disabled = false }: PrimaryButtonProps) {
return (
<TouchableOpacity onPress={onPress} disabled={disabled}>
<Text>{label}</Text>
</TouchableOpacity>
);
}
Using <PrimaryButton label={42} /> now triggers an error, since a label must be text and onPress is missing.
Type State
Give useState a type in angle brackets when the starting value cannot reveal the full shape.
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<Product[]>([]);
The User | null notation is a union. The value is either a user or nothing. TypeScript forces you to check for null before reading its fields.
if (user) {
console.log(user.name); // safe: user exists here
}
Union Types for Fixed Choices
type Status = 'idle' | 'loading' | 'success' | 'error';
const [status, setStatus] = useState<Status>('idle');
setStatus('done'); // error: 'done' is not an allowed value
Type Style Objects
React Native ships helper types so style objects receive autocomplete and checks.
import { StyleSheet, ViewStyle, TextStyle } from 'react-native';
const styles = StyleSheet.create({
card: { padding: 16, borderRadius: 8 } as ViewStyle,
});
Type Navigation
Declare the list of screens and the data each one expects. Navigation calls then become safe.
type RootStackParams = {
Home: undefined;
Details: { productId: number };
};
navigation.navigate('Details', { productId: 7 }); // valid
navigation.navigate('Details'); // error: missing productId
Type API Responses
const loadProducts = async (): Promise<Product[]> => {
const res = await fetch('https://example.com/products');
const data: Product[] = await res.json();
return data;
};
Avoid the any Type
The type any switches checking off. Use it rarely. The type unknown offers a safer choice, since it forces a check before use.
Helpful Habits
- Turn on
"strict": trueintsconfig.json - Keep shared interfaces in a
typesfolder - Let TypeScript infer simple types
- Read error messages slowly, since they usually name the exact problem
Summary
TypeScript catches mistakes while you write. Describe objects with interfaces, type component props and state, and use unions for fixed choices. Typed navigation and typed API responses prevent whole families of runtime errors, and strict mode gives the strongest protection.
