O que é o “is” no TypeScript?

O Junior Martins postou essa dúvida no nosso Discord, e eu respondi ele por lá, mas o Gabe sugeriu que a resposta virasse um post, então aqui está!

O is é usado quando você quer criar seus próprios type guards: você cria uma função que retorna um b…


This content originally appeared on DEV Community and was authored by Fernando Daciuk

O Junior Martins postou essa dúvida no nosso Discord, e eu respondi ele por lá, mas o Gabe sugeriu que a resposta virasse um post, então aqui está!

O is é usado quando você quer criar seus próprios type guards: você cria uma função que retorna um booleano (esse tipo de função se chamada "predicado"), e usa o is para dizer que, se a função retornar true, quer dizer que o valor passado via argumento é de um tipo específico.

Por exemplo: imagine que você vai fazer um request para uma API, para buscar um produto.

A resposta pode ser um objeto com os dados do produto ou null, se o produto não for encontrado.

Poderíamos representar em tipos assim:

type Product = {
    id: string
    name: string
    price: number
}

type ProductResponse = Product | null

Agora vamos fazer uma função que vai fazer esse request (fake, obviamente).. ignore a implementação, a ideia é só retornar um objeto do tipo ProductResponse, ou seja: ou vai retornar um Product, ou vai retornar null:

async function getProduct (id: string): Promise<ProductResponse> {
    const product = {
        id,
        name: 'TV',
        price: 5000
    }

    const possibleResponse = [product, null]
    const index = Math.floor(Math.random() * possibleResponse.length)
    return possibleResponse[index]
}

Ao executar essa função, o retorno vai ser uma Promise de ProductResponse. Se você tentar acessar o valor de price da resposta - já que a função pode retornar um produto - o TS vai mostrar o erro:

Object is possibly 'null'

A chamada seria algo assim:

getProduct('tv123').then(response => {
    console.log(response.price)
})

Para garantir que o objeto não é nulo, precisamos usar um type guard, verificando o tipo do dado para garantir que ele não é nulo antes de acessar as propriedades do objeto:

getProduct('tv123').then(response => {
    if (response === null) {
        // aqui o TS sabe que `response` é null
        return
    }
    // aqui o TS sabe que `response` é `Product`, pois `null`
    // e `Product` são as únicas possíveis opções para `response`
    console.log(response.price)
})

Usar um if com uma comparação por algum tipo (testando se o dado é igual a null, ou usando o typeof, por exemplo), é um type guard interno do TypeScript. Mas pense o seguinte: e se você quiser criar seu próprio type guard? Possivelmente você tentaria fazer algo assim:

function isProduct (value: ProductResponse) {
    return value !== null
}

E então testaria o valor:

getProduct('tv123').then(response => {
    if (!isProduct(response)) {
        return
    }

    console.log(response.price)
})

A surpresa acontece quando descobrimos que o TS agora não consegue inferir que response só será null se cair no if, e dá o mesmo erro:

Object is possibly 'null'.

É aí que entra o is!

Como a função isProduct é apenas uma função que recebe um argumento qualquer, e retorna um valor qualquer, o TS não vai conseguir inferir que o retorno é um Product, e que esse retorno está diretamente relacionado com o argumento passado para a função.

Para fazer o TS entender essa relação, usamos o is: temos que dizer ao TS que, quando executarmos a função isProduct passando o argumento response, se a função retornar true, quer dizer que o argumento É, de fato, um Product.

Para dizer isso ao TS, só precisamos alterar o tipo de retorno da função isProduct:

function isProduct (value: ProductResponse): value is Product {
    return value !== null
}

Pronto! Agora o TS vai saber quando o response é null e quando ele é um Product em um escopo completamente diferente da função isProduct!

getProduct('tv123').then(response => {
    if (!isProduct(response)) {
        // agora o TS sabe - novamente - que `response` é null, pois estamos
        // verificando se `response` NÃO é um `Product`
        return
    }
    // e aqui o TS sabe que `response` é `Product`, pois `null`
    // e `Product` são as únicas possíveis opções para `response`
    console.log(response.price)
})

Podemos também criar um type guard mais genérico, para testar se o valor é null, fazendo uma verificação positiva, ao invés de criar um if negativo, que dificulta um pouco a leitura:

function isNull (value: unknown): value is null  {
  return value === null
}

E então só precisamos usar essa função de type guard:

getProduct('tv123').then(response => {
    if (isNull(response)) {
        // aqui dentro o TS sabe que `response` é null
        return
    }
    // e aqui o TS sabe que `response` é `Product`, pois `null`
    // e `Product` são as únicas possíveis opções para `response`
    console.log(response.price)
})

E tudo funciona como esperado, inclusive o autocomplete das propriedades price, name e id em response ;)

Você pode brincar com esse código direto do Playground do TypeScript!

Por hoje é só! Qualquer dúvida ou sugestão, deixe nos comentários :D

Sobre o autor

Você encontra minhas informações de contato e redes sociais rodando o seguinte comando no seu terminal:

npx fdaciuk


This content originally appeared on DEV Community and was authored by Fernando Daciuk


Print Share Comment Cite Upload Translate Updates
APA

Fernando Daciuk | Sciencx (2022-02-08T18:41:47+00:00) O que é o “is” no TypeScript?. Retrieved from https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/

MLA
" » O que é o “is” no TypeScript?." Fernando Daciuk | Sciencx - Tuesday February 8, 2022, https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/
HARVARD
Fernando Daciuk | Sciencx Tuesday February 8, 2022 » O que é o “is” no TypeScript?., viewed ,<https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/>
VANCOUVER
Fernando Daciuk | Sciencx - » O que é o “is” no TypeScript?. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/
CHICAGO
" » O que é o “is” no TypeScript?." Fernando Daciuk | Sciencx - Accessed . https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/
IEEE
" » O que é o “is” no TypeScript?." Fernando Daciuk | Sciencx [Online]. Available: https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/. [Accessed: ]
rf:citation
» O que é o “is” no TypeScript? | Fernando Daciuk | Sciencx | https://www.scien.cx/2022/02/08/o-que-e-o-is-no-typescript/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.