Aqui está um exemplo de uma resposta padrão da API para um caminho feliz e um caso de erro.

// successful response ✅{	status: 'ok',	responseCode: 200,	data: {...}}// error response ❌{	responseCode: 500,	errorMessage: "Something went wrong 😅";}

Em vez de escrever uma interface para cada resposta e adicionar essas chaves, você pode simplesmente usar o Generics para criar algo como isto:

interface ApiResponse<T>{	errorMessage?: string;	responseCode?: string;	data?: T;}

interface UserData {	name: string;	email: string;}const response: ApiResponse<UserData> = {}

Vinculando genéricos com funções

Vamos supor que temos uma função que usamos para fazer uma solicitação de API ao nosso back-end.

const getRequestTo = (endpoint: string) => {	return fetch(process.env.BE_HOST + endpoint).then(res => res.json())}const userResponse = getRequestTo('/user-data')

O tipo de userResponse seria any. Podemos ter uma melhor implementação TypeScript aqui.

const getRequestTo = async <R>(endpoint: string): Promise<ApiResponse<R>> => {	const request = await fetch(process.env.BE_HOST + endpoint);	const response = await request.json();	return response;};

Podemos criar uma função semelhante para solicitações POST que também usa JSON como parâmetros do tipo B e o servidor retornará uma resposta JSON do tipo R:

const postRequestTo = async <B, R>(	endpoint: string,	body: B): Promise<ApiResponse<R>> => {	const request = await fetch(process.env.BE_HOST + endpoint, {		method: "POST",		body: JSON.stringify(body),	});	const response = await request.json();	return response;};

Da mesma forma, também pode haver uma função de solicitação PATCH, que lida com atualizações parciais de qualquer entidade.

const patchRequestTo = async <B, R>(endpoint: string,body: Partial<B>): Promise<ApiResponse> => {	const request = await fetch(process.env.BE_HOST + endpoint, {    	method: "PATCH",	    body: JSON.stringify(body)    });	const response = await request.json();	return response;};

Aqui está como implementar algo assim:

interface RequestBody {}interface Response {}const createPost = await postRequestTo<RequestBody, Response>('/post', postData);const updatePost = await patchRequestTo<RequestBody, Response>('/post', {	title: "new name"});

Vamos juntar tudo isso com uma simples classe JavaScript:

class ApiService<T> {	constructor(entitySlug: string) {		this.entitySlug = entitySlug;	}	private entitySlug: string;	getOne = async (id: string): Promise<APIResponse<T>> => {		const request = await fetch(process.env.BE_HOST + this.entitySlug + '/' + id);		const response = await request.json();		return response;	};    	getList = async (): Promise<APIResponse<T[]>> => {		const request = await fetch(process.env.BE_HOST + this.entitySlug);		const response = await request.json();		return response;	};	create = async (body: Omit<T, 'id' | 'created' | 'updated'>): Promise<APIResponse<T>> => {		const request = await fetch(process.env.BE_HOST + this.entitySlug, {			method: 'POST',			body: JSON.stringify(body)		});		const response = await request.json();		return response;	};    	update = async (		body: Omit<Partial<T>, 'id' | 'created' | 'updated'>	): Promise<APIResponse<T>> => {		const request = await fetch(process.env.BE_HOST + this.entitySlug + '/' + body.id, {			method: 'PATCH',			body: JSON.stringify(body)		});		const response = await request.json();		return response;	};    	delete = async (id: string): Promise<void> => {		const request = await fetch(process.env.BE_HOST + this.entitySlug + '/' + id, {			method: 'DELETE'		});		const response = await request.json();		return response;	};};

e você pode criar um serviço de entidade como este:

export const postService = new ApiService<Post>('/post');

e está tudo vinculado e pronto para você.

image 70
Sugestão automática de código VS de acordo com a configuração de texto datilografado que implementamos

O texto datilografado tem o potencial de aumentar em dez vezes a experiência do desenvolvedor, se configurado adequadamente. Estas são algumas estratégias para tornar esse processo de configuração mais confortável. Espero que isso ajude você a usar o Typecript melhor em sua base de código atual.