TypeScript Support
Learn how to use qortex with TypeScript for type-safe data fetching. Type definitions, generics, and best practices.
TypeScript Examples
Basic TypeScript Usage
Define types for your data and get full type safety
interface User {
id: string;
name: string;
email: string;
avatar?: string;
}
// Type-safe fetcher
registerFetcher<User[]>(["users"], {
fetcher: async (): Promise<User[]> => {
const response = await fetch("/api/users");
return response.json();
}
});
// Type-safe hook usage
function UsersList() {
const { data: users, isLoading, error } = useQuery<User[]>(["users"]);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{users?.map(user => (
<li key={user.id}>
{user.name} - {user.email}
</li>
))}
</ul>
);
}
Generic Type Parameters
Use generics for flexible type-safe data fetching
// Generic API response type
interface ApiResponse<T> {
data: T;
status: 'success' | 'error';
message?: string;
}
// Type-safe API calls
async function fetchApi<T>(url: string): Promise<T> {
const response = await fetch(url);
const result: ApiResponse<T> = await response.json();
if (result.status === 'error') {
throw new Error(result.message || 'API Error');
}
return result.data;
}
// Register typed fetchers
registerFetcher<User[]>(["users"], {
fetcher: () => fetchApi<User[]>("/api/users")
});
registerFetcher<Post[]>(["posts"], {
fetcher: () => fetchApi<Post[]>("/api/posts")
});
Complex Data Types
Handle complex nested data structures with TypeScript
interface Post {
id: string;
title: string;
content: string;
author: {
id: string;
name: string;
avatar?: string;
};
tags: string[];
createdAt: string;
updatedAt: string;
}
interface PostWithComments extends Post {
comments: Comment[];
}
// Type-safe fetcher with complex data
registerFetcher<PostWithComments>(["post", "id"], {
fetcher: async (key): Promise<PostWithComments> => {
const [, , postId] = key;
const response = await fetch(`/api/posts/${postId}?include=comments`);
return response.json();
}
});
// Type-safe component
function PostDetail({ postId }: { postId: string }) {
const { data: post, isLoading } = useQuery<PostWithComments>(["post", "id", postId]);
if (isLoading) return <div>Loading post...</div>;
if (!post) return <div>Post not found</div>;
return (
<article>
<h1>{post.title}</h1>
<p>By {post.author.name}</p>
<div>{post.content}</div>
<div>
<h3>Comments ({post.comments.length})</h3>
{post.comments.map(comment => (
<div key={comment.id}>
<strong>{comment.author.name}:</strong> {comment.content}
</div>
))}
</div>
</article>
);
}
Type-Safe Configuration
Configure qortex with full type safety
// Type-safe configuration
interface AppConfig {
apiUrl: string;
timeout: number;
retries: number;
}
// Type-safe default config
setDefaultConfig({
staleTime: 5 * 60 * 1000,
refetchOnSubscribe: "stale" as const,
throttleTime: 100,
usePreviousDataOnError: true,
equalityFn: (a: unknown, b: unknown) => {
return JSON.stringify(a) === JSON.stringify(b);
}
});
// Type-safe fetcher options
registerFetcher<User[]>(["users"], {
fetcher: async (): Promise<User[]> => {
const response = await fetch("/api/users");
return response.json();
},
staleTime: 10 * 60 * 1000, // 10 minutes
placeholderData: [] as User[],
equalityFn: (a: User[], b: User[]) => {
return a.length === b.length &&
a.every((user, index) => user.id === b[index]?.id);
}
});
Type Definitions
Fetcher<T>
Function type for data fetching
type Fetcher<T> = (key: string | string[]) => Promise<T>;
EqualityFn<T>
Function type for data equality comparison
type EqualityFn<T> = (a: T, b: T) => boolean;
UseQueryResult<T>
Return type of useQuery hook
interface UseQueryResult<T> {
data: T | undefined;
isLoading: boolean;
isFetching: boolean;
error: Error | null;
refetch: () => Promise<void>;
status: 'idle' | 'fetching' | 'success' | 'error';
isStale: boolean;
updatedAt: number | null;
isPlaceholderData: boolean;
}
FetcherOptions<T>
Options for registering a fetcher
interface FetcherOptions<T> {
fetcher: Fetcher<T>;
staleTime?: number;
placeholderData?: T;
equalityFn?: EqualityFn<T>;
}
TypeScript Best Practices
✅ Do
- • Define interfaces for your data structures
- • Use generic type parameters for flexibility
- • Provide type annotations for fetcher functions
- • Use const assertions for literal types
- • Define custom equality functions with proper types
- • Use type guards for runtime type checking
❌ Don't
- • Use 'any' type unnecessarily
- • Ignore TypeScript errors
- • Forget to type your API responses
- • Use type assertions without validation
- • Mix different data types in the same query
- • Skip type definitions for complex data
Type Safety Benefits
Compile-time Safety
Catch errors before runtime with TypeScript's type checking
Better IntelliSense
Get autocomplete and documentation in your IDE
Refactoring Safety
Safely refactor code with confidence in type safety
Ready for Type Safety?
Now that you understand TypeScript integration, explore more advanced features and configuration options.