Pular para o conteúdo principal

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 install --save @data-client/endpoint
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);
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' });