TypeScript Guide
Full TypeScript support with type inference and type safety.
Type Inference
Storken automatically infers types from your initial values:
const [useStorken] = create({
initialValues: {
count: 0, // inferred as number
name: 'John', // inferred as string
isActive: true, // inferred as boolean
data: null as Data | null // explicit type annotation
}
})
// TypeScript knows the types
const [count, setCount] = useStorken('count')
// count: number
// setCount: (value: number | ((prev: number) => number)) => void
Generic Types
Explicitly specify types using generics for better type safety:
interface User {
id: string
name: string
email: string
role: 'admin' | 'user'
}
// Explicit type annotation
const [user, setUser] = useStorken<User | null>('user', null)
// Type-safe updates
setUser({
id: '123',
name: 'John Doe',
email: 'john@example.com',
role: 'admin'
})
// TypeScript will error on invalid properties
setUser({
id: '123',
name: 'John',
// Error: Property 'email' is missing
})
Typed Configurations
Create fully typed store configurations:
import { create, StorkenConfig } from 'storken'
interface AppState {
user: User | null
theme: 'light' | 'dark'
todos: Todo[]
settings: Settings
}
const config: StorkenConfig<AppState> = {
initialValues: {
user: null,
theme: 'light',
todos: [],
settings: defaultSettings
},
getters: {
user: async (): Promise<User> => {
const res = await fetch('/api/user')
return res.json()
}
},
setters: {
todos: async (storken, todos: Todo[]) => {
await saveTodos(todos)
}
}
}
const [useStorken] = create(config)
Custom Hook Types
Create typed custom hooks for your store:
// store.ts
export const [useStorken, get, set, sky] = create({
initialValues: {
user: null as User | null,
theme: 'light' as Theme,
notifications: [] as Notification[]
}
})
// hooks/useUser.ts
export function useUser() {
const [user, setUser, resetUser, loading] = useStorken<User | null>('user')
const login = async (credentials: Credentials) => {
const user = await authService.login(credentials)
setUser(user)
return user
}
const logout = () => {
resetUser()
authService.logout()
}
return {
user,
loading,
login,
logout,
isAuthenticated: !!user
}
}
Plugin Types
Type your custom plugins for better IDE support:
import { StorkenPlugin, StorkenInstance } from 'storken'
interface LoggerPluginOptions {
prefix?: string
logLevel?: 'debug' | 'info' | 'warn' | 'error'
}
interface LoggerPluginAPI {
log: (message: string) => void
setLevel: (level: LoggerPluginOptions['logLevel']) => void
}
const createLoggerPlugin = (
options?: LoggerPluginOptions
): StorkenPlugin<LoggerPluginAPI> => {
return (storken: StorkenInstance) => {
let level = options?.logLevel || 'info'
const prefix = options?.prefix || '[Storken]'
storken.on('set', (value) => {
if (level !== 'error') {
console.log(`${prefix} ${storken.key} updated:`, value)
}
})
return {
log: (message: string) => {
console.log(`${prefix} ${message}`)
},
setLevel: (newLevel) => {
level = newLevel
}
}
}
}
// Use with type safety
const [useStorken] = create({
plugins: {
logger: createLoggerPlugin({ prefix: '[App]' })
}
})
const [value, , , , , plugins] = useStorken('key')
plugins.logger.log('Hello') // Fully typed!
Async Types
Handle async operations with proper typing:
interface ApiResponse<T> {
data: T
error?: string
status: number
}
const [useStorken] = create({
getters: {
posts: async (storken, userId: string): Promise<Post[]> => {
const response = await fetch(`/api/users/${userId}/posts`)
const result: ApiResponse<Post[]> = await response.json()
if (result.error) {
throw new Error(result.error)
}
return result.data
}
}
})
// Usage with proper typing
function UserPosts({ userId }: { userId: string }) {
const [posts, , , loading, refetch] = useStorken<Post[]>('posts')
useEffect(() => {
refetch(userId) // Pass typed arguments
}, [userId, refetch])
if (loading) return <Loading />
return (
<div>
{posts?.map(post => (
<PostCard key={post.id} post={post} />
))}
</div>
)
}
Utility Types
Storken exports useful utility types:
import type {
StorkenConfig, // Configuration object type
StorkenHookReturn, // Hook return tuple type
StorkenGetter, // Getter function type
StorkenSetter, // Setter function type
StorkenPlugin, // Plugin function type
StorkenInstance, // Store instance type
Sky // Sky instance type
} from 'storken'
// Use utility types for your abstractions
type AppGetter<T> = StorkenGetter<T, [userId: string]>
type AppSetter<T> = StorkenSetter<T>
// Create typed helpers
function createAppStore<T extends Record<string, any>>(
config: StorkenConfig<T>
) {
return create(config)
}
💡 TypeScript Best Practices
- • Always define interfaces for complex state shapes
- • Use generics when the type isn't inferrable
- • Export types alongside your store for reusability
- • Leverage type inference where possible
- • Use strict mode for better type safety