Skip to content

Instantly share code, notes, and snippets.

@AlexVipond
Created September 5, 2023 14:26
Show Gist options
  • Save AlexVipond/299818a845dc8b4a6c901b22ab512e84 to your computer and use it in GitHub Desktop.
Save AlexVipond/299818a845dc8b4a6c901b22ab512e84 to your computer and use it in GitHub Desktop.
Automatic type inference for fetched data, using generics and `infer`
async function getPageData () {
const users = await get('/users')
const user1 = await get('/users/1')
const usersWithParams = await get('/users?limit=10')
const user1WithParams = await get('/users/1?hello=world')
return {
users,
user1,
usersWithParams,
user1WithParams,
}
}
async function get<Endpoint extends AnyEndpoint> (
endpoint: Endpoint
): Promise<ResponseJson<Endpoint>> {
const response = await fetch(`/api${endpoint}`)
return await response.json()
}
type AnyEndpoint = `/${keyof ResponseJsonByEndpoint}/${number}?${string}`
| `/${keyof ResponseJsonByEndpoint}/${number}`
| `/${keyof ResponseJsonByEndpoint}?${string}`
| `/${keyof ResponseJsonByEndpoint}`
type ResponseJson<Endpoint extends AnyEndpoint> =
Endpoint extends `/${infer E extends keyof ResponseJsonByEndpoint}/${number}?${string}`
? ResponseJsonByEndpoint[E][number]
: Endpoint extends `/${infer E extends keyof ResponseJsonByEndpoint}/${number}`
? ResponseJsonByEndpoint[E][number]
: Endpoint extends `/${infer E extends keyof ResponseJsonByEndpoint}?${string}`
? ResponseJsonByEndpoint[E]
: Endpoint extends `/${infer E extends keyof ResponseJsonByEndpoint}`
? ResponseJsonByEndpoint[E]
: never
interface ResponseJsonByEndpoint {
'users': User[],
'tasks': Task[],
}
interface User {
id: number,
name: string,
password: 'password',
}
interface Task {
id: number,
name: string,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment