@types packages are needed.
Setup
Preact’s TypeScript definitions are included by default. Just install Preact and start using TypeScript:{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"jsx": "react-jsx",
"jsxImportSource": "preact",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"]
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Type Definitions
Preact’s type definitions are located in the source code:src/index.d.ts- Core Preact typessrc/jsx.d.ts- JSX type definitionshooks/src/index.d.ts- Hooks type definitionscompat/src/index.d.ts- React compatibility types
src/index.d.ts, hooks/src/index.d.ts
Component Types
- Function Components
- Class Components
Function components are typed using the Or use the shorthand (recommended):
FunctionComponent type:Props with Children
TheComponentChildren type represents valid children:
FunctionComponent which includes children automatically:
Hooks with TypeScript
Event Handlers
Preact provides specific event types for all DOM events:JSX.TargetedEvent<T, E>- Generic eventJSX.TargetedMouseEvent<T>- Mouse eventsJSX.TargetedKeyboardEvent<T>- Keyboard eventsJSX.TargetedFocusEvent<T>- Focus events
Refs with TypeScript
Context with TypeScript
Custom Hooks
Type your custom hooks like regular functions:Generic Components
Create reusable components that work with any type:Utility Types
Preact exports useful utility types:Best Practices
// Good: Type is inferred
const [count, setCount] = useState(0);
// Unnecessary: Type already inferred
const [count, setCount] = useState<number>(0);
// Necessary: Complex type or null initial value
const [user, setUser] = useState<User | null>(null);
// Good: Reusable interface
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary';
}
function Button({ label, onClick, variant = 'primary' }: ButtonProps) {
return (
<button className={variant} onClick={onClick}>
{label}
</button>
);
}
type AsyncState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function UserProfile() {
const [state, setState] = useState<AsyncState<User>>({
status: 'idle'
});
if (state.status === 'loading') return <div>Loading...</div>;
if (state.status === 'error') return <div>{state.error.message}</div>;
if (state.status === 'success') return <div>{state.data.name}</div>;
return null;
}
Next Steps
Hooks
Learn about hooks with full TypeScript support
Context
Type-safe context with TypeScript