Imagine que você tem a seguinte situação:
Você tem uma aplicação que busca por músicas no Spotify e nessa aplicação você mostra o
Você então cria 2 funções para acessar a API do Spotify
-
getUser
para chamar a API que irá buscar os dados do usuário -
getSong
que irá retornar uma lista de músicas do Spotify
Então você teria o seguinte código:
type APIResponse<T> = {
data: T;
error: Error;
}
type User = {
email: string;
}
type Song = { id: string; title: string };
const getUser = async (fetchUrl: string): APIResponse<User> => {
const res = await fetch(fetchUrl);
return res;
}
const getSong = async (fetchUrl: string): APIResponse<Song> => {
const res = await fetch(fetchUrl);
return res;
}
Depois de implementar as 2 funções, você percebe que elas são muito parecidas. As 2 recebem uma url
que é passada para dentro do método fetch
. Esse método faz a chamada para a API
e depois retorna o resultado.
E aí, você pode pensar
poxa, já que elas são tão parecidas, acho que vou criar uma função que reduz a quantidade de código repetido
const fetchApi = async (fetchUrl: string): APIResponse<User | Song> => {
const res = await fetch(fetchUrl);
return res;
}
const userResppnse = await fetchApi('https://apiUser...');
const songResponse = await fetchApi('https://apiSong...');
Já parece que ficou melhor. Agora temos menos código duplicado e menor possibilidade de erro.
Mas você vai ter um problema de Typescript
😟
O tipo da variável userResponse
está como APIResponse<User | Song>
então se você tentar fazer isso:
const userResponse = await fetchApi('https://...');
console.log(userResponse.data.email);
Você vai tomar o seguinte erro:
Property 'email' does not exist on type 'User | Songs[]'.
Property 'email' does not exist on type 'Songs[]'
O Typescript não consegue dizer se a propriedade data
da variável userResponse
é um User
ou um Song
e por isso ele previne que você chame a propriedade email
que é exclusiva do User
.
Isso garante que se por exemplo isso acontecer:
const userResponse = fetch('https://apiSong...');
Você não vai ter problemas mais pra frente.
Type guards
Os type guards
são uma forma de dizer para o Typescript
qual tipo nós esperamos.
Podemos criar um type guard
de usuário que garante o tipo User
da seguinte forma:
const isUser = (data: User | Song): data is User => (data as User).email !== undefined;
Estamos criando a função isUser
que aceita o tipo data: User | Song
e que retorna um data is User
. A expressão is User
diz que eu, como desenvolvedor, garanto que o retorno da minha função é do tipo User
.
O que falta é a implementação dessa verificação. Já que o tipo Song
não tem o campo email
podemos verificar se a variável data
possuí ele.
Se possuir, podemos dizer que data
é do tipo User
.
E com isso, podemos executar o seguinte código sem problemas de Typescript
:
if(isUser(userResponse.data)) {
console.log(userResponse.data.email)
};
Assim, o Typescript
não vai mostrar um erro porque você disse que a função isUser
retorna User
e nada mais.
Não tem possibilidade da variável data
ser do tipo Song
por exemplo.
E para finalizar, o type guard do tipo Song
seria assim:
const isSong = (data: User | Song): data is Song => (data as Song).title !== undefined;
if(isSong(songResponse.data)) {
console.log(songResponse.data.title);
}
Através dos type guards
você consegue ter maior controle sobre a tipagem do seu código. Tudo isso em tempo de runtime
, o que é bem legal 🤘
Apesar de ser uma boa adição na sua base de código, o
type guards
é propenso a falhas já que quem define a função para validar o tipo é o próprio desenvolvedor.Para resolver essas falhas e realmente trabalhar com um
typchecking
emruntime
, sugiro dar uma lida nesse artigo do pessoal do Unsplash. O artigo destaca o porquê detype guards
definidos pelo usuário não serem tão seguros e o que fazer nesses casos.
Galera, é isso por hoje. Fiz esse artigo porque acabei me deparando com algumas situações na minha aplicação que funcionariam melhor se tivesse um type guard
implementado. E apesar de serem muito úteis, não vejo muita gente usando no dia a dia, então fica aqui minha contribuição. Espero que consigam aproveitar de alguma forma 😉
E se vocês sentiram falta de alguma explicação, ficaram com alguma dúvida ou só querem trocar uma ideia, podem me marcar ou mandar DM no twitter 🤙
Top comments (0)