Endpoints padrão em TypeScript
Os Endpoints descrevem uma API assíncrona. Isso inclui tanto o comportamento em tempo de execução quanto (opcionalmente) a tipagem.
- NPM
- Yarn
- pnpm
- esm.sh
yarn add @data-client/endpoint
npm install --save @data-client/endpoint
pnpm add @data-client/endpoint
<script type="module">
import * from 'https://esm.sh/@data-client/endpoint';
</script>
- TypeScript
- JavaScript
interface Todo {
userId: number;
id: number;
title: string;
completed: boolean;
}
interface Params {
id: number;
}
const fetchTodoDetail = ({ id }: Params): Promise<Todo> =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`).then(res =>
res.json(),
);
const todoDetail = new Endpoint(fetchTodoDetail);
const fetchTodoDetail = ({ id }) =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`).then(res =>
res.json(),
);
const todoDetail = new Endpoint(fetchTodoDetail);
Exemplo de uso
console.log(await todoDetail({ id: '1' }));
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Provavelmente vamos querer usar este endpoint em muitos lugares com necessidades diferentes. Ao definir uma função reutilizável com apenas a definição de rede, possibilitamos seu uso em qualquer contexto.
Isso é especialmente útil quando começamos a adicionar mais informações relacionadas ao endpoint. Por exemplo, as definições de TypeScript nos ajudam a evitar erros comuns e erros de digitação, e aceleram o desenvolvimento com autocomplete.
Ao acoplar fortemente a definição da interface, enquanto acoplamos fracamente o seu uso, reduzimos o código boilerplate, a complexidade e os erros comuns, ao mesmo tempo que aumentamos o desempenho e possibilitamos consistência e integridade globais na aplicação, mesmo diante de dados assíncronos pouco confiáveis.
Mais do que apenas uma função
Além de uma função assíncrona e de tipos (opcionais), os Endpoints são objetos, o que permite que forneçam qualquer informação adicional relevante sobre o próprio endpoint.
Por exemplo, para permitir a integração com um cache, bem como saber quando recalcular e/ou buscar novamente quando os parâmetros mudam, os Endpoints têm um membro key() que serializa o endpoint e os parâmetros em uma string única.
console.log(todoDetail.key({ id: '1' }));
// fetchTodoDetail {"id":"1"}
Membros
O segundo argumento, opcional, é um objeto com o qual inicializar o endpoint. Ao evitar arrow functions, podemos usar this para acessar outros membros que definimos.
const todoDetailWithCustomizedKey = new Endpoint(fetchTodoDetail, {
key({ id }) {
return `${this.endpointIdentifier}/${id}`;
},
endpointIdentifier: 'todoDetail',
});
console.log(todoDetailWithCustomizedKey.key({ id: '1' }));
// todoDetail/1
Endpoint.extend()
Por conveniência, extend() permite extensões de um endpoint por herança prototipal com tipagem correta.
Isso reduz bastante o código boilerplate quando padrões sólidos são estabelecidos para uma API, como autenticação.
Aqui mostramos os benefícios de personalizar o membro method.
const fetchTodoDetail = function ({ id }) {
return fetch(`${this.urlBase}/todos/${id}`, { method: this.method }).then(
res => res.json(),
);
};
const todoDetail = new Endpoint(fetchTodoDetail, {
method: 'GET',
urlBase: 'https://jsonplaceholder.typicode.com',
});
const todoCreate = todoDetail.extend({ method: 'POST' });
const todoUpdate = todoDetail.extend({ method: 'PUT' });