Typing callback props that your components accept.
Simple Callback Props
tsxtype ButtonProps = { onClick: () => void; // No arguments, no return }; function Button({ onClick }: ButtonProps) { return <button onClick={onClick}>Click</button>; }
Callback with Arguments
tsxtype UserCardProps = { user: User; onSelect: (userId: string) => void; onEdit: (user: User) => void; onDelete: (userId: string) => Promise<void>; }; function UserCard({ user, onSelect, onEdit, onDelete }: UserCardProps) { return ( <div onClick={() => onSelect(user.id)}> <h3>{user.name}</h3> <button onClick={() => onEdit(user)}>Edit</button> <button onClick={() => onDelete(user.id)}>Delete</button> </div> ); }
Optional Callbacks
tsxtype ModalProps = { isOpen: boolean; onClose: () => void; // Required onConfirm?: () => void; // Optional onCancel?: () => void; // Optional }; function Modal({ isOpen, onClose, onConfirm, onCancel }: ModalProps) { return ( <div> {/* Always available */} <button onClick={onClose}>×</button> {/* Check before calling */} {onConfirm && <button onClick={onConfirm}>Confirm</button>} {onCancel && <button onClick={onCancel}>Cancel</button>} </div> ); }
Passing Event Through
tsxtype SearchInputProps = { value: string; onChange: (value: string) => void; onSubmit: () => void; }; function SearchInput({ value, onChange, onSubmit }: SearchInputProps) { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { onChange(e.target.value); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { onSubmit(); } }; return ( <input value={value} onChange={handleChange} onKeyDown={handleKeyDown} /> ); } // Parent component - clean API <SearchInput value={query} onChange={setQuery} // Just receives the string onSubmit={handleSearch} />
Generic Event Props
tsxtype SelectProps<T> = { options: T[]; value: T; onChange: (value: T) => void; getLabel: (item: T) => string; getValue: (item: T) => string; }; function Select<T>({ options, value, onChange, getLabel, getValue }: SelectProps<T>) { return ( <select value={getValue(value)} onChange={e => { const selected = options.find(o => getValue(o) === e.target.value); if (selected) onChange(selected); }} > {options.map(option => ( <option key={getValue(option)} value={getValue(option)}> {getLabel(option)} </option> ))} </select> ); }