feat: extract types from endpoint
chore: change example and readme Closes #24
This commit is contained in:
parent
96c7ea554c
commit
651e09bc31
9 changed files with 37 additions and 20 deletions
|
@ -36,7 +36,7 @@ const MoviesEndpoint: Endpoint<MoviesResponse, void> = {
|
||||||
type MoviesResponse = Movie[];
|
type MoviesResponse = Movie[];
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { data, loading } = useRequest<MoviesResponse>(MoviesEndpoint);
|
const { data, loading } = useRequest(MoviesEndpoint);
|
||||||
|
|
||||||
return !data ? (
|
return !data ? (
|
||||||
<div>{ loading ? 'Loading...' : 'Something went wrong' }</div>
|
<div>{ loading ? 'Loading...' : 'Something went wrong' }</div>
|
||||||
|
|
|
@ -21,11 +21,11 @@ export type MoviesResponse = {
|
||||||
items: Movie[],
|
items: Movie[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MovieEndpoint: Endpoint<MovieResponse, void, MovieParams> = {
|
export const MovieEndpoint: Endpoint<MovieResponse, never, MovieParams> = {
|
||||||
method: Method.GET,
|
method: Method.GET,
|
||||||
url: ({ id }) => `/action-adventure/${id}`,
|
url: ({ id }) => `/action-adventure/${id}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MovieParams = Readonly<{ id: React.Key }>;
|
export type MovieParams = Readonly<{ id: React.Key }>;
|
||||||
|
|
||||||
export type MovieResponse = Movie[];
|
export type MovieResponse = Movie;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useRequest } from 'react-rest-request';
|
import { useRequest } from 'react-rest-request';
|
||||||
import { Link, useParams } from 'react-router-dom';
|
import { Link, useParams } from 'react-router-dom';
|
||||||
import { MovieEndpoint, MovieParams, MovieResponse, MoviesEndpoint, MoviesResponse } from './endpoint';
|
import { MovieEndpoint, MoviesEndpoint } from './endpoint';
|
||||||
|
|
||||||
|
|
||||||
export function MoviesPage() {
|
export function MoviesPage() {
|
||||||
const { data, loading } = useRequest<MoviesResponse>(MoviesEndpoint);
|
const { data, loading } = useRequest(MoviesEndpoint);
|
||||||
|
|
||||||
return !data ? (
|
return !data ? (
|
||||||
<div>{ loading ? 'Loading...' : 'Something went wrong' }</div>
|
<div>{ loading ? 'Loading...' : 'Something went wrong' }</div>
|
||||||
|
@ -27,7 +27,7 @@ export function MoviesPage() {
|
||||||
|
|
||||||
export function MoviePage() {
|
export function MoviePage() {
|
||||||
const params = useParams<{ id: string}>();
|
const params = useParams<{ id: string}>();
|
||||||
const { data, loading } = useRequest<MovieResponse, void, MovieParams>(
|
const { data, loading } = useRequest(
|
||||||
MovieEndpoint,
|
MovieEndpoint,
|
||||||
{
|
{
|
||||||
params,
|
params,
|
||||||
|
|
|
@ -8,9 +8,13 @@ export enum Method {
|
||||||
DELETE = 'DELETE',
|
DELETE = 'DELETE',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Endpoint<R, V, P = void> = Readonly<{
|
export type Endpoint<R, V, P = never> = Readonly<{
|
||||||
method: Method;
|
method: Method;
|
||||||
url: string | ((params: P) => string);
|
url: string | ((params: P) => string);
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
transformResponseData?: (data: any) => R;
|
transformResponseData?: (data: any) => R;
|
||||||
}>
|
}>
|
||||||
|
|
||||||
|
export type ExtractEndpointResponse<E> = E extends Endpoint<infer R, any, any> ? R : E extends Endpoint<infer R, any> ? R : never;
|
||||||
|
export type ExtractEndpointVariables<E> = E extends Endpoint<any, infer V, any> ? V : E extends Endpoint<any, infer V> ? V : never;
|
||||||
|
export type ExtractEndpointParams<E> = E extends Endpoint<any, any, infer P> ? P : never;
|
||||||
|
|
|
@ -2,13 +2,13 @@ import React, { useCallback, useMemo } from 'react';
|
||||||
import invariant from 'tiny-invariant';
|
import invariant from 'tiny-invariant';
|
||||||
import isEqual from 'lodash.isequal';
|
import isEqual from 'lodash.isequal';
|
||||||
import { useClient } from './client-hook';
|
import { useClient } from './client-hook';
|
||||||
import { Endpoint } from './endpoint';
|
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
||||||
import { PublicRequestState, RequestAction, requestReducer, RequestState } from './reducer';
|
import { PublicRequestState, RequestAction, requestReducer, RequestState } from './reducer';
|
||||||
import { useRequestContext } from './request-context';
|
import { useRequestContext } from './request-context';
|
||||||
import { ClientResponse } from './client';
|
import { ClientResponse } from './client';
|
||||||
import { isFunction } from './misc';
|
import { isFunction } from './misc';
|
||||||
|
|
||||||
export type LazyRequestConfig<R, V, P = void> = Readonly<{
|
export type LazyRequestConfig<R, V, P = never> = Readonly<{
|
||||||
variables?: V;
|
variables?: V;
|
||||||
params?: P;
|
params?: P;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
|
@ -23,8 +23,13 @@ export type LazyRequestHandlerConfig<R, V, P> = Readonly<
|
||||||
|
|
||||||
export type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
|
export type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
|
||||||
|
|
||||||
export function useLazyRequest<R = Record<string, any>, V = Record<string, any>, P = void>(
|
export function useLazyRequest<
|
||||||
endpoint: Endpoint<R, V, P>,
|
E extends Endpoint<R, V, P>,
|
||||||
|
R = ExtractEndpointResponse<E>,
|
||||||
|
V = ExtractEndpointVariables<E>,
|
||||||
|
P = ExtractEndpointParams<E>
|
||||||
|
>(
|
||||||
|
endpoint: E,
|
||||||
config?: LazyRequestConfig<R, V, P>,
|
config?: LazyRequestConfig<R, V, P>,
|
||||||
): [RequestHandler<R, V, P>, PublicRequestState<R>] {
|
): [RequestHandler<R, V, P>, PublicRequestState<R>] {
|
||||||
const [client] = useClient();
|
const [client] = useClient();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import invariant from 'tiny-invariant';
|
import invariant from 'tiny-invariant';
|
||||||
import { Endpoint, Method } from './endpoint';
|
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables, Method } from './endpoint';
|
||||||
import { LazyRequestConfig, useLazyRequest } from './lazy-request-hook';
|
import { LazyRequestConfig, useLazyRequest } from './lazy-request-hook';
|
||||||
|
|
||||||
export type RequestConfig<R, V, P> = Readonly<
|
export type RequestConfig<R, V, P> = Readonly<
|
||||||
|
@ -10,8 +10,13 @@ export type RequestConfig<R, V, P> = Readonly<
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
||||||
export function useRequest<R = Record<string, any>, V = Record<string, any>, P = void>(
|
export function useRequest<
|
||||||
endpoint: Endpoint<R, V, P>,
|
E extends Endpoint<R, V, P>,
|
||||||
|
R = ExtractEndpointResponse<E>,
|
||||||
|
V = ExtractEndpointVariables<E>,
|
||||||
|
P = ExtractEndpointParams<E>
|
||||||
|
>(
|
||||||
|
endpoint: E,
|
||||||
config?: RequestConfig<R, V, P>,
|
config?: RequestConfig<R, V, P>,
|
||||||
) {
|
) {
|
||||||
invariant(
|
invariant(
|
||||||
|
|
5
target/endpoint.d.ts
vendored
5
target/endpoint.d.ts
vendored
|
@ -6,9 +6,12 @@ export declare enum Method {
|
||||||
PATCH = "PATCH",
|
PATCH = "PATCH",
|
||||||
DELETE = "DELETE"
|
DELETE = "DELETE"
|
||||||
}
|
}
|
||||||
export declare type Endpoint<R, V, P = void> = Readonly<{
|
export declare type Endpoint<R, V, P = never> = Readonly<{
|
||||||
method: Method;
|
method: Method;
|
||||||
url: string | ((params: P) => string);
|
url: string | ((params: P) => string);
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
transformResponseData?: (data: any) => R;
|
transformResponseData?: (data: any) => R;
|
||||||
}>;
|
}>;
|
||||||
|
export declare type ExtractEndpointResponse<E> = E extends Endpoint<infer R, any, any> ? R : E extends Endpoint<infer R, any> ? R : never;
|
||||||
|
export declare type ExtractEndpointVariables<E> = E extends Endpoint<any, infer V, any> ? V : E extends Endpoint<any, infer V> ? V : never;
|
||||||
|
export declare type ExtractEndpointParams<E> = E extends Endpoint<any, any, infer P> ? P : never;
|
||||||
|
|
6
target/lazy-request-hook.d.ts
vendored
6
target/lazy-request-hook.d.ts
vendored
|
@ -1,7 +1,7 @@
|
||||||
import { Endpoint } from './endpoint';
|
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
||||||
import { PublicRequestState } from './reducer';
|
import { PublicRequestState } from './reducer';
|
||||||
import { ClientResponse } from './client';
|
import { ClientResponse } from './client';
|
||||||
export declare type LazyRequestConfig<R, V, P = void> = Readonly<{
|
export declare type LazyRequestConfig<R, V, P = never> = Readonly<{
|
||||||
variables?: V;
|
variables?: V;
|
||||||
params?: P;
|
params?: P;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
|
@ -12,4 +12,4 @@ export declare type LazyRequestHandlerConfig<R, V, P> = Readonly<LazyRequestConf
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}>;
|
}>;
|
||||||
export declare type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
|
export declare type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
|
||||||
export declare function useLazyRequest<R = Record<string, any>, V = Record<string, any>, P = void>(endpoint: Endpoint<R, V, P>, config?: LazyRequestConfig<R, V, P>): [RequestHandler<R, V, P>, PublicRequestState<R>];
|
export declare function useLazyRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: LazyRequestConfig<R, V, P>): [RequestHandler<R, V, P>, PublicRequestState<R>];
|
||||||
|
|
4
target/request-hook.d.ts
vendored
4
target/request-hook.d.ts
vendored
|
@ -1,9 +1,9 @@
|
||||||
import { Endpoint } from './endpoint';
|
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
||||||
import { LazyRequestConfig } from './lazy-request-hook';
|
import { LazyRequestConfig } from './lazy-request-hook';
|
||||||
export declare type RequestConfig<R, V, P> = Readonly<LazyRequestConfig<R, V, P> & {
|
export declare type RequestConfig<R, V, P> = Readonly<LazyRequestConfig<R, V, P> & {
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
}>;
|
}>;
|
||||||
export declare function useRequest<R = Record<string, any>, V = Record<string, any>, P = void>(endpoint: Endpoint<R, V, P>, config?: RequestConfig<R, V, P>): Pick<Readonly<{
|
export declare function useRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: RequestConfig<R, V, P>): Pick<Readonly<{
|
||||||
data: R | null;
|
data: R | null;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
isCalled: boolean;
|
isCalled: boolean;
|
||||||
|
|
Reference in a new issue