<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Keveen Tenereli - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Keveen Tenereli - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 09 May 2026 13:42:13 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/author/keveen/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Como criar uma aplicação de lista de tarefas com React, TypeScript, NodeJS e MongoDB ]]>
                </title>
                <description>
                    <![CDATA[ Neste tutorial, usaremos TypeScript em ambos os lados (client e servidor) para desenvolver uma aplicação de lista de tarefas do zero com React, NodeJS, Express e MongoDB. Então, vamos começar pelo planejamento da API.  * API com NodeJS, Express, MongoDB e TypeScript  * Início  * Criar um ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-criar-uma-aplicacao-de-lista-de-tarefas-com-react-typescript-nodejs-e-mongodb/</link>
                <guid isPermaLink="false">64b80cbab04bf0067ce246ed</guid>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Keveen Tenereli ]]>
                </dc:creator>
                <pubDate>Tue, 03 Oct 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/cover-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-build-a-todo-app-with-react-typescript-nodejs-and-mongodb/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Build a Todo App with React, TypeScript, NodeJS, and MongoDB</a>
      </p><p>Neste tutorial, usaremos TypeScript em ambos os lados (<em>client</em> e servidor) para desenvolver uma aplicação de lista de tarefas do zero com React, NodeJS, Express e MongoDB.</p><p>Então, vamos começar pelo planejamento da API.</p><ul><li>API com NodeJS, Express, MongoDB e TypeScript</li><li>Início</li><li>Criar um tipo de tarefas</li><li>Criar um modelo de tarefas</li><li>Criar controladores de API</li><li>Get, Add, Update e Delete de tarefas</li><li>Criar rotas da API</li><li>Criar um servidor</li><li>Lado do <em>client </em>com React e TypeScript</li><li>Configuração</li><li>Criar um tipo de tarefas</li><li>Buscar dados da API</li><li>Criar os componentes</li><li>Adicionar formulário de tarefas</li><li>Exibir uma tarefa</li><li>Buscar e exibir dados</li><li>Recursos</li></ul><p><em>Vamos lá.</em></p><h2 id="api-com-nodejs-express-mongodb-e-typescript">API com NodeJS, Express, MongoDB e TypeScript</h2><h3 id="in-cio">Início</h3><p>Se você é novo nisso, pode começar com <a href="https://www.ibrahima-ndaw.com/blog/a-practical-guide-to-typescript/">A Practical Guide to TypeScript</a> ou com <a href="https://www.ibrahima-ndaw.com/blog/graphql-api-express-mongodb/">How to build an API from scratch with Node JS, Express, and MongoDB</a> (textos em inglês) para tirar o máximo possível deste tutorial. Caso contrário, vamos começar.</p><p>Para criar uma aplicação do NodeJS, você precisar executar esse comando no terminal:</p><pre><code class="language-shell">  yarn init
</code></pre><p>Ele perguntará algumas coisas e, então, a aplicação será inicializada. Você pode pular isso adicionando uma flag <code>-y</code> ao comando.</p><p>Depois, estruture o projeto da seguinte maneira:</p><pre><code>├── dist
├── node_modules
├── src
   ├── app.ts
   ├── controllers
   |  └── todos
   |     └── index.ts
   ├── models
   |  └── todo.ts
   ├── routes
   |  └── index.ts
   └── types
      └── todo.ts
├── nodemon.json
├── package.json
├── tsconfig.json
</code></pre><p>Como você pode observar, a estrutura desse arquivo é relativamente simples. O diretório <code>dist</code> servirá como uma pasta para os resultados uma vez que o código tenha sido compilado para JavaScript simples.</p><p>Também temos um arquivo <code>app.ts</code> que é o ponto de entrada do servidor. Os controladores, tipos e rotas também estão em suas respectivas pastas.</p><p>Agora, precisamos configurar o arquivo <code>tsconfig.json</code> para auxiliar o compilador a seguir nossas preferências.</p><ul><li>tsconfig.json</li></ul><pre><code class="language-js">{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist/js",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["src/types/*.ts", "node_modules", ".vscode"]
}
</code></pre><p>Aqui, temos as quatro principais propriedades para destacar:</p><p><code>outDir</code>: diz para o compilador colocar o código compilado dentro da pasta <code>dist/js</code>.</p><p><code>rootDir</code>: informa ao TypeScript para compilar todos os arquivos <code>.ts</code> que se encontrarem na pasta <code>src</code>.</p><p><code>include</code>: diz ao compilador para incluir arquivos que estão no diretório e nos sub-diretórios de <code>src</code>.</p><p><code>exclude</code>: excluirá os arquivos ou pastas inseridos no <em>array </em>durante o tempo de compilação.</p><p>Agora, podemos instalar as dependências para habilitar o TypeScript no projeto. Por padrão, essea aplicação usaria JavaScript.</p><p>Existem duas maneiras de usar TypeScript em uma aplicação do NodeJS. Localmente, no projeto, ou globalmente, em nossa máquina. Vou optar pela última opção com base em minha preferência pessoal, mas você pode continuar com a forma local se quiser.</p><p>Vamos executar o seguinte comando no terminal e instalar o TypeScript.</p><pre><code class="language-shell">  yarn add typescript -g
</code></pre><p>A flag <code>g</code> permite instalar o TypeScript globalmente. Isso faz com que seja acessível de qualquer lugar no computador.</p><p>Depois, vamos adicionar algumas dependências para poder usar o Express e o MongoDB.</p><pre><code class="language-shell">  yarn add express cors mongoose
</code></pre><p>Também precisamos instalar tipos como depêndencias de desenvolvimento para ajudar o compilador do TypeScript a entender os pacotes.</p><pre><code class="language-shell">  yarn add -D @types/node @types/express @types/mongoose @types/cors
</code></pre><p>Agora, o TypeScript não vai mais gritar com você – ele usará esses tipos para definir as bibliotecas que acabamos de instalar.</p><p>Também precisamos adicionar outras dependências para poder compilar o código em TypeScript e inicializar o servidor simultaneamente.</p><pre><code class="language-shell">  yarn add -D concurrently nodemon
</code></pre><p>Com isso pronto, podemos atualizar o arquivo <code>package.json</code> com os scripts necessários para iniciar o servidor.</p><ul><li>package.json</li></ul><pre><code class="language-js">  "scripts": {
    "build": "tsc",
    "start": "concurrently \"tsc -w\" \"nodemon dist/js/app.js\""
  }
</code></pre><p><code>concurrently</code> ajudará a compilar o código TypeScript, observar mudanças e iniciar o servidor simultaneamente. Dito isso, podemos iniciar o servidor – embora, ainda não tenhamos criado algo significativo nesse sentido. Vamos corrigir isso na próxima sessão.</p><h3 id="criar-um-tipo-de-tarefas">Criar um tipo de tarefas</h3><ul><li>types/todo.ts</li></ul><pre><code class="language-ts">import { Document } from "mongoose"

export interface ITodo extends Document {
  name: string
  description: string
  status: boolean
}
</code></pre><p>Aqui, temos uma interface de tarefas (Todo - em português, tarefa ou afazer) que estende o tipo <code>Document</code> fornecido pelo <code>mongoose</code>. Vamos utilizar essa interface mais tarde para que interaja com o MongoDB. Dito isso, agora, podemos definir como o modelo de tarefa deve ser.</p><h3 id="criar-um-modelo-de-tarefa">Criar um modelo de tarefa</h3><ul><li>models/todo.ts</li></ul><pre><code class="language-ts">import { ITodo } from "./../types/todo"
import { model, Schema } from "mongoose"

const todoSchema: Schema = new Schema(
  {
    name: {
      type: String,
      required: true,
    },

    description: {
      type: String,
      required: true,
    },

    status: {
      type: Boolean,
      required: true,
    },
  },
  { timestamps: true }
)

export default model&lt;ITodo&gt;("Todo", todoSchema)
</code></pre><p>Como podemos ver aqui, começamos implementando a interface <code>ITodo</code> e algumas utilidades do <code>mongoose</code>. Essa última parte ajuda a definir o esquema Todo e também a passar <code>ITodo</code> como um tipo para o <code>model</code> antes de exportá-lo.</p><p>Com isso, agora podemos usar o modelo de tarefa em outros arquivos para interagir com o banco de dados.</p><h3 id="criar-controladores-api">Criar controladores API</h3><h4 id="get-add-update-e-delete-de-tarefas">Get, Add, Update e Delete de tarefas</h4><ul><li>controllers/todos/index.ts</li></ul><pre><code class="language-ts">import { Response, Request } from "express"
import { ITodo } from "./../../types/todo"
import Todo from "../../models/todo"

const getTodos = async (req: Request, res: Response): Promise&lt;void&gt; =&gt; {
  try {
    const todos: ITodo[] = await Todo.find()
    res.status(200).json({ todos })
  } catch (error) {
    throw error
  }
}
</code></pre><p>Aqui, primeiro, precisamos importar alguns tipos do <code>express</code>, pois quero digitar os valores explicitamente. Se você quiser, pode deixar o TypeScript inferi-los para você.</p><p>Depois, usamos a função <code>getTodos()</code> para puxar os dados. Ela recebe os parâmetros <code>req</code> e <code>res</code> e retorna uma <em>promise</em>.</p><p>Com a ajuda do modelo <code>Todo</code> que criamos mais cedo, agora, podemos receber dados do MongoDB e retornar uma resposta com o <em>array </em>de tarefas.</p><ul><li>controllers/todos/index.ts</li></ul><pre><code class="language-ts">const addTodo = async (req: Request, res: Response): Promise&lt;void&gt; =&gt; {
  try {
    const body = req.body as Pick&lt;ITodo, "name" | "description" | "status"&gt;

    const todo: ITodo = new Todo({
      name: body.name,
      description: body.description,
      status: body.status,
    })

    const newTodo: ITodo = await todo.save()
    const allTodos: ITodo[] = await Todo.find()

    res
      .status(201)
      .json({ message: "Todo added", todo: newTodo, todos: allTodos })
  } catch (error) {
    throw error
  }
}
</code></pre><p>Como você pode ver, a função <code>addTodo()</code> recebe o objeto body, que contém dados introduzidos pelo usuário.</p><p>Depois, fazemos uso de <em>typecasting</em> para evitar erros de digitação e restringir a variável <code>body</code> para que corresponda a <code>ITodo</code> e, então, criamos uma tarefa (um <em>Todo</em>) baseado no modelo.</p><p>Com isso pronto, podemos salvar a tarefa no banco de dados e retornar a resposta que contém a tarefa criada, além de atualizar o <em>array </em>de tarefas.</p><ul><li>controllers/todos/index.ts</li></ul><pre><code class="language-ts">const updateTodo = async (req: Request, res: Response): Promise&lt;void&gt; =&gt; {
  try {
    const {
      params: { id },
      body,
    } = req
    const updateTodo: ITodo | null = await Todo.findByIdAndUpdate(
      { _id: id },
      body
    )
    const allTodos: ITodo[] = await Todo.find()
    res.status(200).json({
      message: "Todo updated",
      todo: updateTodo,
      todos: allTodos,
    })
  } catch (error) {
    throw error
  }
}
</code></pre><p>Para atualizar uma tarefa, precisamos extrair a id e o body do objeto <code>req</code> e, então, passá-los para <code>findByIdAndUpdate()</code>. Essa utilidade encontrará a tarefa no banco de dados e a atualizará. Uma vez que a operação tenha sido completada, podemos retornar os dados atualizados ao usuário.</p><ul><li>controllers/todos/index.ts</li></ul><pre><code class="language-ts">const deleteTodo = async (req: Request, res: Response): Promise&lt;void&gt; =&gt; {
  try {
    const deletedTodo: ITodo | null = await Todo.findByIdAndRemove(
      req.params.id
    )
    const allTodos: ITodo[] = await Todo.find()
    res.status(200).json({
      message: "Todo deleted",
      todo: deletedTodo,
      todos: allTodos,
    })
  } catch (error) {
    throw error
  }
}

export { getTodos, addTodo, updateTodo, deleteTodo }
</code></pre><p>A função <code>deleteTodo()</code> permite que você exclua uma tarefa do banco de dados. Aqui, puxamos a id de <code>req</code> e passamos como um argumento em <code>findByIdAndRemove()</code> para accessar a tarefa correspondente e exclui-la do banco de dados.</p><p>Depois, exportamos as funções para que possamos usá-las em outros arquivos. Dito isso, podemos criar algumas rotas para a API e usar esses métodos para lidar com os pedidos.</p><h3 id="criar-rotas-da-api">Criar rotas da API</h3><ul><li>routes/index.ts</li></ul><pre><code class="language-ts">import { Router } from "express"
import { getTodos, addTodo, updateTodo, deleteTodo } from "../controllers/todos"

const router: Router = Router()

router.get("/todos", getTodos)

router.post("/add-todo", addTodo)

router.put("/edit-todo/:id", updateTodo)

router.delete("/delete-todo/:id", deleteTodo)

export default router
</code></pre><p>Como você pode ver aqui, temos quatro rotas para obter, adicionar, atualizar e excluir tarefas do banco de dados. Como já criamos as funções, a única coisa que temos que fazer é importar os métodos e passá-los como parâmetros para lidar com os pedidos.</p><p>Até então, cobrimos bastante. Ainda não temos, no entanto, um servidor para inicializar. Vamos corrigir isso na próxima seção.</p><h3 id="criar-um-servidor">Criar um servidor</h3><p>Antes de criar o servidor, precisamos, primeiro, adicionar algumas variáveis do ambiente que guardarão as credenciais do MongoDB no arquivo <code>nodemon.json</code>.</p><ul><li>nodemon.json</li></ul><pre><code class="language-js">{
    "env": {
        "MONGO_USER": "seu-nome-de-usuario",
        "MONGO_PASSWORD": "sua-senha",
        "MONGO_DB": "nome-do-banco-de-dados"
    }
}
</code></pre><p>Você pode obter as credenciais criando um cluster no <a href="https://www.mongodb.com/cloud/atlas">MongoDB Atlas</a>.</p><ul><li>app.ts</li></ul><pre><code class="language-ts">import express, { Express } from "express"
import mongoose from "mongoose"
import cors from "cors"
import todoRoutes from "./routes"

const app: Express = express()

const PORT: string | number = process.env.PORT || 4000

app.use(cors())
app.use(todoRoutes)

const uri: string = `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@clustertodo.raz9g.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&amp;w=majority`
const options = { useNewUrlParser: true, useUnifiedTopology: true }
mongoose.set("useFindAndModify", false)

mongoose
  .connect(uri, options)
  .then(() =&gt;
    app.listen(PORT, () =&gt;
      console.log(`Server running on http://localhost:${PORT}`)
    )
  )
  .catch(error =&gt; {
    throw error
  })
</code></pre><p>Aqui, começamos importando a biblioteca <code>express</code>, que permite que acessemos o método <code>use()</code>, que, por sua vez, ajuda a lidar com as rotas das tarefas.</p><p>Depois, usamos o pacote <code>mongoose</code> para conectar com o MongoDB, ao adicionar ao URL as credenciais que estão no arquivo <code>nodemon.json</code>.</p><p>Dito isso, se agora conectarmos com sucesso ao MongoDB, o servidor iniciará. Se for apropriado, um erro será mostrado.</p><p>Terminamos de criar a API com Node, Express, TypeScript e MongoDB. Vamos começar a criar a aplicação do lado do <em>client</em> com React e TypeScript.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/giphy.gif" class="kg-image" alt="giphy" width="350" height="198" loading="lazy"></figure><h2 id="lado-do-client-com-react-e-typescript">Lado do <em>client</em> com React e TypeScript</h2><h3 id="configura-o">Configuração</h3><p>Para criar uma aplicação com React, usarei o create-react-app – você pode usar outros métodos, se quiser.</p><p>Então, vamos rodar o seguinte comando no terminal:</p><pre><code class="language-shell">  npx create-react-app my-app --template typescript
</code></pre><p>Depois, instale a biblioteca Axios para poder buscar dados remotamente.</p><pre><code class="language-shell">  yarn add axios
</code></pre><p>Uma vez que a instalação tenha terminado, vamos ter a estrutura do nosso projeto do seguinte modo:</p><pre><code>├── node_modules
├── public
├── src
|  ├── API.ts
|  ├── App.test.tsx
|  ├── App.tsx
|  ├── components
|  |  ├── AddTodo.tsx
|  |  └── TodoItem.tsx
|  ├── index.css
|  ├── index.tsx
|  ├── react-app-env.d.ts
|  ├── setupTests.ts
|  └── type.d.ts
├── tsconfig.json
├── package.json
└── yarn.lock
</code></pre><p>Aqui, temos uma estrutura de arquivos relativamente simples. A principal coisa para se notar é que <code>src/type.d.ts</code> vai manter dois tipos. Como eu vou usá-los em quase todo arquivo, eu adicionei a extensão <code>.d.ts</code> para fazer com que os tipos sejam disponibilizados globalmente. Agora, não precisamos mais importá-los.</p><h3 id="criar-um-tipo-de-tarefa">Criar um tipo de tarefa</h3><ul><li>src/type.d.ts</li></ul><pre><code class="language-ts">interface ITodo {
  _id: string
  name: string
  description: string
  status: boolean
  createdAt?: string
  updatedAt?: string
}

interface TodoProps {
  todo: ITodo
}

type ApiDataType = {
  message: string
  status: string
  todos: ITodo[]
  todo?: ITodo
}
</code></pre><p>Aqui, a interface <code>ITodo</code> precisa espelhar a forma dos dados da API. Como não temos o <code>mongoose</code> aqui, precisamos adicionar outras propriedades para combiná-las com o tipo definido na API.</p><p>Depois, usaremos essa mesma interface para o <code>TodoProps</code>, que é a anotação do tipo para a <em>props </em>que será recebida pelo componente responsável por renderizar os dados.</p><p>Agora que definimos os nossos tipos, vamos agora começar a buscar dados da API.</p><h3 id="buscar-dados-da-api">Buscar dados da API</h3><ul><li>src/API.ts</li></ul><pre><code class="language-ts">import axios, { AxiosResponse } from "axios"

const baseUrl: string = "http://localhost:4000"

export const getTodos = async (): Promise&lt;AxiosResponse&lt;ApiDataType&gt;&gt; =&gt; {
  try {
    const todos: AxiosResponse&lt;ApiDataType&gt; = await axios.get(
      baseUrl + "/todos"
    )
    return todos
  } catch (error) {
    throw new Error(error)
  }
}
</code></pre><p>Como você pode ver, precisamos importar o <code>axios</code> para fazer solicitações de dados da API. Depois, usamos a função <code>getTodos()</code> para pegar dados do servidor. Ela retornará uma <em>promise </em>do tipo <code>AxiosResponse</code>, que contém as tarefas buscadas, as quais precisam combinar com o tipo <code>ApiDataType</code>.</p><ul><li>src/API.ts</li></ul><pre><code class="language-ts">export const addTodo = async (
  formData: ITodo
): Promise&lt;AxiosResponse&lt;ApiDataType&gt;&gt; =&gt; {
  try {
    const todo: Omit&lt;ITodo, "_id"&gt; = {
      name: formData.name,
      description: formData.description,
      status: false,
    }
    const saveTodo: AxiosResponse&lt;ApiDataType&gt; = await axios.post(
      baseUrl + "/add-todo",
      todo
    )
    return saveTodo
  } catch (error) {
    throw new Error(error)
  }
}
</code></pre><p>Essa função recebe os dados inseridos pelo usuário como um argumento e retorna a <em>promise</em>. Aqui, precisamos omitir a propriedade <code>_id</code>, porque o MongoDB a criará na hora.</p><ul><li>src/API.ts</li></ul><pre><code class="language-ts">export const updateTodo = async (
  todo: ITodo
): Promise&lt;AxiosResponse&lt;ApiDataType&gt;&gt; =&gt; {
  try {
    const todoUpdate: Pick&lt;ITodo, "status"&gt; = {
      status: true,
    }
    const updatedTodo: AxiosResponse&lt;ApiDataType&gt; = await axios.put(
      `${baseUrl}/edit-todo/${todo._id}`,
      todoUpdate
    )
    return updatedTodo
  } catch (error) {
    throw new Error(error)
  }
}
</code></pre><p>Para atualizar uma tarefa, precisamos passar os dados atualizados e a <code>_id</code> do objeto. Aqui, precisamos mudar o <code>status</code> da tarefa. É por isso que eu pego apenas a propriedade que precisamos antes de mandar o pedido ao servidor.</p><ul><li>src/API.ts</li></ul><pre><code class="language-ts">export const deleteTodo = async (
  _id: string
): Promise&lt;AxiosResponse&lt;ApiDataType&gt;&gt; =&gt; {
  try {
    const deletedTodo: AxiosResponse&lt;ApiDataType&gt; = await axios.delete(
      `${baseUrl}/delete-todo/${_id}`
    )
    return deletedTodo
  } catch (error) {
    throw new Error(error)
  }
}
</code></pre><p>Aqui, também temos a função que recebe como parâmetro a propriedade <code>_id</code> e retorna a <em>promise</em>.</p><p>Com isso pronto, agora podemos acessar a pasta <code>components</code> e adicionar algumas linhas de código importantes aos seus arquivos.</p><h3 id="criar-os-componentes">Criar os componentes</h3><h4 id="adicionar-o-formul-rio-de-tarefas">Adicionar o formulário de tarefas</h4><ul><li>components/AddTodo.tsx</li></ul><pre><code class="language-js">import React from "react"

type Props = TodoProps &amp; {
  updateTodo: (todo: ITodo) =&gt; void
  deleteTodo: (_id: string) =&gt; void
}

const Todo: React.FC&lt;Props&gt; = ({ todo, updateTodo, deleteTodo }) =&gt; {
  const checkTodo: string = todo.status ? `line-through` : ""
  return (
    &lt;div className="Card"&gt;
      &lt;div className="Card--text"&gt;
        &lt;h1 className={checkTodo}&gt;{todo.name}&lt;/h1&gt;
        &lt;span className={checkTodo}&gt;{todo.description}&lt;/span&gt;
      &lt;/div&gt;
      &lt;div className="Card--button"&gt;
        &lt;button
          onClick={() =&gt; updateTodo(todo)}
          className={todo.status ? `hide-button` : "Card--button__done"}
        &gt;
          Complete
        &lt;/button&gt;
        &lt;button
          onClick={() =&gt; deleteTodo(todo._id)}
          className="Card--button__delete"
        &gt;
          Delete
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  )
}

export default Todo
</code></pre><p>Como você pode ver, aqui, temos um componente funcional do tipo <code>React.FC</code> (FC significa componente funcional – do inglês, <em>functional component</em>). Ele recebe como <em>prop </em>o método <code>saveTodo()</code>, que nos permite salvar os dados no banco de dados.</p><p>Depois, temos o <em>state</em> <code>formData</code>, que precisa combinar com o tipo do <code>ITodo</code> para satisfazer o compilador. Essa é a razão para o passarmos para o <em>hook</em> <code>useState</code>. Também precisamos adicionar um tipo alternativo (<code>{}</code>), pois o <em>state</em> incial será um objeto vazio.</p><p>Com isso, podemos seguir em frente e visualizar os dados que foram buscados.</p><h3 id="exibir-uma-tarefa"><strong>Exibir uma tarefa</strong></h3><ul><li>components/TodoItem.tsx</li></ul><pre><code class="language-jsx">import React from "react"

type Props = TodoProps &amp; {
  updateTodo: (todo: ITodo) =&gt; void
  deleteTodo: (_id: string) =&gt; void
}

const Todo: React.FC&lt;Props&gt; = ({ todo, updateTodo, deleteTodo }) =&gt; {
  const checkTodo: string = todo.status ? `line-through` : ""
  return (
    &lt;div className="Card"&gt;
      &lt;div className="Card--text"&gt;
        &lt;h1 className={checkTodo}&gt;{todo.name}&lt;/h1&gt;
        &lt;span className={checkTodo}&gt;{todo.description}&lt;/span&gt;
      &lt;/div&gt;
      &lt;div className="Card--button"&gt;
        &lt;button
          onClick={() =&gt; updateTodo(todo)}
          className={todo.status ? `hide-button` : "Card--button__done"}
        &gt;
          Complete
        &lt;/button&gt;
        &lt;button
          onClick={() =&gt; deleteTodo(todo._id)}
          className="Card--button__delete"
        &gt;
          Delete
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  )
}

export default Todo
</code></pre><p>Aqui, precisamos estender o tipo <code>TodoProps</code> e acrescentar as funções <code>updateTodo</code> e<code>deleteTodo</code> para lidar apropriadamente com as <em>props </em>recebidas pelo componente.</p><p>Agora, uma vez que o objeto Todo (a tarefa) tenha sido passado, poderemos exibir e adicionar as funcões necessárias para atualizar ou excluir uma tarefa.</p><p>Ótimo! Podemos agora acessar o arquivo <code>App.tsx</code> e adicionar a última peça do quebra-cabeça.</p><h3 id="buscar-e-exibir-dados">Buscar e exibir dados</h3><ul><li>App.tsx</li></ul><pre><code class="language-jsx">import React, { useEffect, useState } from 'react'
import TodoItem from './components/TodoItem'
import AddTodo from './components/AddTodo'
import { getTodos, addTodo, updateTodo, deleteTodo } from './API'

const App: React.FC = () =&gt; {
  const [todos, setTodos] = useState&lt;ITodo[]&gt;([])

  useEffect(() =&gt; {
    fetchTodos()
  }, [])

  const fetchTodos = (): void =&gt; {
    getTodos()
    .then(({ data: { todos } }: ITodo[] | any) =&gt; setTodos(todos))
    .catch((err: Error) =&gt; console.log(err))
  }
</code></pre><p>Aqui, primeiro, precisamos importar os componentes e funções utilitárias do <code>API.ts</code>. &nbsp;Depois, passamos um <em>array </em>do tipo <code>ITodo</code> para o <code>useState</code> e o inicializamos com um <em>array </em>vazio.</p><p>O método <code>getTodos()</code> retorna uma <em>promise</em> – logo, podemos acessar a função <code>then</code> e atualizar o <em>state </em>com os dados buscados ou lançar um erro, se algum ocorrer.</p><p>Com isso pronto, podemos chamar a função <code>fetchTodos()</code> quando o componente é montado com sucesso.</p><ul><li>App.tsx</li></ul><pre><code class="language-jsx">const handleSaveTodo = (e: React.FormEvent, formData: ITodo): void =&gt; {
  e.preventDefault()
  addTodo(formData)
    .then(({ status, data }) =&gt; {
      if (status !== 201) {
        throw new Error("Error! Todo not saved")
      }
      setTodos(data.todos)
    })
    .catch(err =&gt; console.log(err))
}
</code></pre><p>Uma vez que o formulário é submetido, o usamos para enviar o pedido ao servidor. Se a tarefa foi salva com sucesso, atualizamos os dados. Caso contrário, um erro será lançado.</p><ul><li>App.tsx</li></ul><pre><code class="language-jsx">const handleUpdateTodo = (todo: ITodo): void =&gt; {
  updateTodo(todo)
    .then(({ status, data }) =&gt; {
      if (status !== 200) {
        throw new Error("Error! Todo not updated")
      }
      setTodos(data.todos)
    })
    .catch(err =&gt; console.log(err))
}

const handleDeleteTodo = (_id: string): void =&gt; {
  deleteTodo(_id)
    .then(({ status, data }) =&gt; {
      if (status !== 200) {
        throw new Error("Error! Todo not deleted")
      }
      setTodos(data.todos)
    })
    .catch(err =&gt; console.log(err))
}
</code></pre><p>As funções para excluir ou atualizar uma tarefa são bastante similares. As duas recebem um parâmetro, enviam seu pedido e recebem de volta uma resposta. Então, elas verificam se o pedido teve sucesso e lidam com ele de maneira apropriada.</p><ul><li>App.tsx</li></ul><pre><code class="language-jsx">  return (
    &lt;main className='App'&gt;
      &lt;h1&gt;My Todos&lt;/h1&gt;
      &lt;AddTodo saveTodo={handleSaveTodo} /&gt;
      {todos.map((todo: ITodo) =&gt; (
        &lt;TodoItem
          key={todo._id}
          updateTodo={handleUpdateTodo}
          deleteTodo={handleDeleteTodo}
          todo={todo}
        /&gt;
      ))}
    &lt;/main&gt;
  )
}

export default App
</code></pre><p>Aqui, iteramos pelo <em>array </em><code>todos</code> e, então, passamos para o <code>TodoItem</code> os dados esperados.</p><p>Navegue até a pasta que contém o lado do servidor da aplicação e execute os seguinte comando no terminal:</p><pre><code class="language-shell">yarn start
</code></pre><p>Faça o mesmo no lado do client da aplicação:</p><p>Você deve ver que nossa aplicação de lista de tarefas funciona como esperado.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/09/todo-image.png" class="kg-image" alt="todo-image" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/09/todo-image.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/09/todo-image.png 868w" sizes="(min-width: 720px) 720px" width="868" height="669" loading="lazy"></figure><p>Ótimo! Com esse toque final, terminamos de criar uma aplicação de lista de tarefas com TypeScript, React, NodeJs, Express e MongoDB.</p><p>Você pode encontrar o <a href="https://github.com/ibrahima92/fullstack-typescript-mern-todo">código-fonte aqui</a>.</p><p>Você pode encontrar outros ótimos conteúdos como esse no <a href="https://github.com/ibrahima92/fullstack-typescript-mern-todo">blog do autor</a> (em inglês) e seguir o autor <a href="https://twitter.com/ibrahima92_">no Twitter</a> para ser notificado.</p><p>Agradecemos pela leitura.</p><h2 id="recursos-em-ingl-s-no-github-e-no-site-do-autor-">Recursos (em inglês, no GitHub e no site do autor)</h2><p><a href="https://github.com/typescript-cheatsheets/react-typescript-cheatsheet">Ficha informativa de TypeScript e React</a></p><p><a href="https://www.ibrahima-ndaw.com/blog/advanced-typescript-cheat-sheet/">Ficha informativa de tipos avançados em TypeScript (com exemplos)</a></p><p><a href="https://github.com/typescript-cheatsheets">Fichas informativas de TypeScript</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Coerção de tipo em Javascript explicada ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Alexey Samoshkin [Editado em 2/5/2018]: esta publicação, agora, também está disponível em russo [https://medium.com/@sergeybulavyk/%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%82%D0%B8%D0%BF%D0%BE%D0%B2-%D0%B2-javascript-35a15ddfc333] . Agradeço a Serj Bulavyk pelos seus esforços. Conheça as engines A coerção de tipo é o processo de converter o valor de um tipo em outro (como uma string em um número, um ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/coercao-de-tipo-em-javascript-explicada/</link>
                <guid isPermaLink="false">634dc73a95867606153ff167</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Keveen Tenereli ]]>
                </dc:creator>
                <pubDate>Mon, 16 Jan 2023 00:45:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/01/1_7awmfn1lq2McPz8ggapndw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">JavaScript type coercion explained</a>
      </p><p>Escrito por: Alexey Samoshkin</p><p><strong>[Editado em 2/5/2018]</strong>: esta publicação, agora, também está <a href="https://medium.com/@sergeybulavyk/%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%82%D0%B8%D0%BF%D0%BE%D0%B2-%D0%B2-javascript-35a15ddfc333">disponível em russo</a>. Agradeço a Serj Bulavyk pelos seus esforços.</p><h4 id="conhe-a-as-engines">Conheça as engines</h4><p>A <strong>coerção de tipo</strong> é o processo de converter o valor de um tipo em outro (como uma string em um número, um objeto para um valor booleano etc.). Qualquer tipo, seja primitivo ou um objeto, é sujeito a coerção de tipo. Para relembrar, os tipos primitivos são: <code>number</code>, <code>string</code>, <code>boolean</code>, <code>null</code>, <code>undefined</code> e <code>symbol</code> (este último adicionado na ES6).</p><p>Como um exemplo de coerção de tipo na prática, observe a <a href="https://dorey.github.io/JavaScript-Equality-Table/">Tabela de Comparação do JavaScript</a>, que mostra como o operador de igualdade <code>==</code> se comporta para diferentes tipos, <code>a</code> e <code>b</code>. Essa matriz parece intimidadora devido à coerção de tipo implícita que o operador <code>==</code> realiza, sendo quase impossível lembrar de todas essas combinações. Você, no entanto, não precisa fazer isso. Basta aprender os princípios fundamentais da coerção de tipo.</p><p>Este artigo detalha o modo como a coerção de tipo funciona em JavaScript. Ele vai preparar você com o conhecimento essencial para que você se sinta confiante em explicar o que cada uma das expressões a seguir resulta. No final deste artigo, mostrarei as repostas e as explicarei.</p><pre><code>true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] &gt; null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == ‘x’
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0</code></pre><p>Sim, essa é uma lista cheia de coisas bobas que você pode fazer como desenvolvedor. Em 90% dos casos de uso, é melhor evitar a coerção de tipo implícita. Considere essa lista como um exercício de aprendizado para testar seu conhecimento sobre o funcionamento da coerção de tipo. Se você estiver entediado, pode encontrar mais exemplos em <a href="https://wtfjs.com/">wtfjs.com</a>.</p><p>Falando nisso, às vezes, você pode se deparar com questões desse tipo em uma entrevista para um emprego como desenvolvedor JavaScript. Então, continue lendo.</p><h3 id="coer-o-impl-cita-x-expl-cita">Coerção implícita x explícita</h3><p>A coerção de tipo pode ser explícita ou implícita.</p><p>Quando um desenvolvedor expressa a intenção de converter entre tipos escrevendo o código apropriado, como <code>Number(valor)</code>, isso é chamado de <strong>coerção de tipo explícita</strong> (ou, em inglês, <em>type casting</em>).</p><p>Como o JavaScript é uma linguagem fracamente tipada, valores também podem ser convertidos entre tipos diferentes automaticamente, o que é chamado de <strong>coerção de tipo implícita</strong>. Isso acontece geralmente quando você aplica operadores à valores de diferentes tipos, como <code>1 == null</code>, <code>2/'5'</code>, <code>null + new Date()</code>, ou pode ser provocado pelo contexto em torno, como ocorre com <code>if (valor) {…}</code>, onde <code>valor</code> é transformado em booleano.</p><p>Um operador que não provoca a coerção de tipo implícita é <code>===</code>, que é chamado de operador de igualdade estrita. O operador de igualdade fraco <code>==</code> por outro lado, realiza tanto a comparação como a coerção de tipo, se necessário.</p><p>A coerção de tipo implícita é uma faca de dois gumes: é uma grande fonte de frustração e defeitos, mas também um mecanismo útil que nos permite escrever menos código sem perder a legibilidade.</p><h3 id="tr-s-tipos-de-convers-o">Três tipos de conversão</h3><p>A primeira regra para aprender é que há apenas três tipos de conversão de tipo em JavaScript:</p><ul><li>para string</li><li>para booleano</li><li>para número</li></ul><p>A segunda, a lógica de conversão para tipos primitivos e para objetos, funciona de modos diferentes, mas ambos podem ser convertidos apenas desses três modos.</p><p>Vamos começar com os tipos primitivos primeiro.</p><h3 id="convers-o-em-strings">Conversão em strings</h3><p>Para converter explicitamente valores para uma string, aplique a função <code>String()</code>. A coerção implícita é provocada pelo operador binário <code>+</code>, quando qualquer operando é uma string:</p><pre><code>String(123) // explícita
123 + ''    // implícita</code></pre><p>Todos os valores primitivos são convertidos para strings naturalmente como você pode imaginar:</p><pre><code>String(123)                   // '123'
String(-12.3)                 // '-12.3'
String(null)                  // 'null'
String(undefined)             // 'undefined'
String(true)                  // 'true'
String(false)                 // 'false'</code></pre><p>A conversão de <code>symbol</code> é um pouco complicada, porque ele somente pode ser convertido explicitamente, não implicitamente. <a href="https://leanpub.com/understandinges6/read/#leanpub-auto-symbol-coercion">Leia mais neste artigo</a> (em inglês) sobre as regras de coerção em <code>Symbol</code>.</p><pre><code>String(Symbol('my symbol'))   // 'Symbol(my symbol)'
'' + Symbol('my symbol')      // TypeError</code></pre><h3 id="convers-o-em-booleano">Conversão em booleano</h3><p>Para explicitamente converter um valor para booleano, aplique a função <code>Boolean()</code>. A conversão implícita acontece em um contexto lógico, ou é causada pelos operadores lógicos ( <code>||</code> <code>&amp;&amp;</code> <code>!</code>) .</p><pre><code>Boolean(2)          // explícita
if (2) { ... }      // implícita devido ao contexto lógico
!!2                 // implícita devido ao operador lógico
2 || 'hello'        // implícita devido ao operador lógico</code></pre><p><strong>Nota: </strong>os operadores lógicos, como &nbsp;<code>||</code> e <code>&amp;&amp;</code>, realizam a conversão em booleano internamente, mas, na verdade, &nbsp;<a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Expressions_and_Operators#operadores_l%C3%B3gicos">retornam o valor dos operandos originais</a>, mesmo se eles não forem booleanos.</p><pre><code>// retorna o número 123, em vez de retornar true
// 'hello' e 123 ainda são coagidos à boleano internalmente para calcular a expressão
let x = 'hello' &amp;&amp; 123;   // x === 123</code></pre><p>Assim, existem apenas 2 resultados possíveis de conversão para booleano: <code>true</code> ou <code>false</code>. Fica mais fácil lembrar a lista de valores falsos.</p><pre><code>Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false</code></pre><p>Qualquer valor que não está na lista é convertido para <code>true</code>, incluindo objetos, funções, <code>Array</code>, <code>Date</code>, tipos definidos pelo usuário, entre outros. Símbolos são valores verdadeiros. Objetos vazios e arrays são valores verdadeiros também.</p><pre><code>Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true</code></pre><h3 id="convers-o-em-n-meros">Conversão em números</h3><p>Para uma conversão explícita, basta aplicar a função <code>Number()</code>, da mesma maneira que você fez com <code>Boolean()</code> e <code>String()</code> .</p><p>A conversão implícita é complicada, pois ocorre em mais casos:</p><ul><li>operadores de comparação (<code>&gt;</code>, <code>&lt;</code>, <code>&lt;=</code>,<code>&gt;=</code>)</li><li>operadores bitwise ( <code>|</code> <code>&amp;</code> <code>^</code> <code>~</code>)</li><li>operadores aritméticos (<code>-</code> <code>+</code> <code>*</code> <code>/</code> <code>%</code> ). Observe que o binário <code>+</code> não causa a conversão numérica, quando qualquer operando é uma string.</li><li>operador <code>+</code> unário</li><li>operador de igualdade <code>==</code> (incluindo <code>!=</code>). Observe que <code>==</code> não causa conversão numérica quando ambos os operandos são strings.</li></ul><pre><code>Number('123')   // conversão explícita
+'123'          // conversão implícita
123 != '456'    // conversão implícita
4 &gt; '5'         // conversão implícita
5/null          // conversão implícita
true | 0        // conversão implícita</code></pre><p>Aqui vemos como os valores primitivos são convertidos para números:</p><pre><code>Number(null)                   // 0
Number(undefined)              // NaN
Number(true)                   // 1
Number(false)                  // 0
Number(" 12 ")                 // 12
Number("-12.34")               // -12.34
Number("\n")                   // 0
Number(" 12s ")                // NaN
Number(123)                    // 123</code></pre><p>Quando uma string está sendo convertida para um número, a <em>engine</em> primeiro remove espaços em branco no começo e final, caracteres <code>\n</code>, <code>\t</code>, retornando <code>NaN</code> se a string aparada não representar um número válido. Se a string estiver vazia, ela retorna <code>0</code>.</p><p><code>null</code> e <code>undefined</code> são tratados de maneira diferente: <code>null</code> se torna <code>0</code> e <code>undefined</code> se torna <code>NaN</code>.</p><p>Símbolos não podem ser convertidos em números, seja explicitamente, seja implicitamente. Além disso, <code>TypeError</code> é lançado, em vez de converter silenciosamente para <code>NaN</code>, como acontece com <code>undefined</code>. Veja mais sobre as regras de conversão de símbolos na <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Symbol#convers%C3%B5es_de_tipos_de_s%C3%ADmbolos">MDN</a>.</p><pre><code>Number(Symbol('my symbol'))    // TypeError
+Symbol('123')                 // TypeError</code></pre><p>Há <strong>duas regras especiais</strong> para se lembrar:</p><ol><li>Quando <code>==</code> está sendo aplicado a <code>null</code> ou <code>undefined</code>, a conversão numérica não acontece. <code>null</code> se iguala somente a <code>null</code> ou <code>undefined</code> e nada mais.</li></ol><pre><code>null == 0               // false, null não é convertido em 0
null == null            // true
undefined == undefined  // true
null == undefined       // true</code></pre><p>2. <code>NaN</code> não se iguala a nada, nem a si mesmo.</p><pre><code>if (valor !== valor) { console.log("Nós estamos lidando com NaN aqui") }</code></pre><h3 id="coer-o-de-tipo-para-objetos">Coerção de tipo para objetos</h3><p>Até agora, vimos a coerção de tipo para valores primitivos. Isso não é muito emocionante.</p><p>Quando se trata de objetos e qunado a engine encountra expressões como <code>[1] + [2,3]</code>, primeiro é preciso converter um objeto para um valor primitivo, que então é convertido para o tipo final. Ainda são apenas três os tipos de conversão: em números, em strings e em booleanos.</p><p>O caso mais simples é a conversão em booleano: qualquer valor não primitivo é sempre coagido a <code>true</code>, não importando se um objeto ou array é vazio ou não.</p><p>Objetos são convertidos para números primitivos através do método interno <code>[[ToPrimitive]]</code>, que é responsável tanto pela conversão em números como em strings.</p><p>Aqui está uma pseudoimplementação do método <code>[[ToPrimitive]]</code>:</p><p><code>[[ToPrimitive]]</code> é passado com um valor de entrada e com uma preferência de tipo de conversão: <code>Number</code> ou <code>String</code>. O <code>preferredType</code> (tipo preferido, em português) é opcional.</p><p>As conversões em números e em strings fazem uso de dois métodos do objeto de entrada: <code>valueOf</code> e <code>toString</code> . Ambos os métodos são declarados em <code>Object.prototype</code> e, assim, estão disponíveis para qualquer método derivado, como <code>Date</code>, <code>Array</code> etc.</p><p>Em geral, o algoritmo é o seguinte:</p><ol><li>Se a entrada já é um valor primitivo, não faça nada e retorne-a.</li><li>Chame <code>input.toString()</code> e, se o resultado for de um tipo primitivo, retorne-o.</li><li>Chame <code>input.valueOf()</code> e, se o resultado for de um tipo primitivo, retorne-o.</li><li>Se nem <code>input.toString()</code> nem <code>input.valueOf()</code> resultam em um tipo primitivo, lance <code>TypeError</code>.</li></ol><p>As conversões em números primeiro chamam <code>valueOf</code> (3) indo depois para <code>toString</code> (2). A conversão em strings faz o oposto: <code>toString</code> (2) seguido de <code>valueOf</code> (3).</p><p>A maior parte dos tipos integrados não possui <code>valueOf</code>, nem tem <code>valueOf</code> retornando o próprio objeto <code>this</code>, que, então, é ignorado porque não é de um tipo primitivo. Por isso, conversões em números e em strings podem funcionar do mesmo jeito — ambas acabam chamando <code>toString()</code>.</p><p>Operadores diferentes podem ocasionar conversões em números ou em strings com a ajuda do parâmetro <code>preferredType</code>. Existem, contudo, duas exceções: o operador de igualdade <code>==</code> e o operador binário <code>+</code>, que acarretam modos de conversão padrão (<code>preferredType</code> não é especificado, ou é iguala ao <code>default</code>). Nesse caso, a maior parte dos tipos integrados assume uma conversão em número por padrão, com exceção de <code>Date</code>, que faz a conversão em string. </p><p>Um exemplo de comportamento de conversão de <code>Date</code>:</p><p>Você pode sobrescrever os métodos padrão <code>toString()</code> e <code>valueOf()</code> para associar a conversão lógica de objeto para tipo primitivo.</p><p>Perceba como <code>bj + ''</code> retorna<code>'101'</code> como string. O operador <code>+</code> ocasiona um método de conversão padrão e, como dito antes, <code>Object</code> assume uma conversão em número como padrão, usando, assim, o método <code>valueOf()</code> primeiro, em vez de <code>toString()</code>.</p><h3 id="m-todo-symbol-toprimitive-da-es6">Método Symbol.toPrimitive da ES6</h3><p>Na ES5, você pode associar à lógica de conversão de objeto para tipo primitivo sobrescrevendo os métodos <code>toString</code> e<code>valueOf</code>.</p><p>Na ES6, você pode ir mais longe e substituir completamente a rotina interna <code>[[ToPrimitive]]</code>, implementando o método <code>[Symbol.toPrimtive]</code> em um objeto.</p><h3 id="exemplos">Exemplos</h3><p>Armados com a teoria, agora, vamos voltar aos nossos exemplos:</p><pre><code>true + false             // 1
12 / "6"                 // 2
"number" + 15 + 3        // 'number153'
15 + 3 + "number"        // '18number'
[1] &gt; null               // true
"foo" + + "bar"          // 'fooNaN'
'true' == true           // false
false == 'false'         // false
null == ''               // false
!!"false" == !!"true"    // true
['x'] == 'x'             // true 
[] + null + 1            // 'null1'
[1,2,3] == [1,2,3]       // false
{}+[]+{}+[1]             // '0[object Object]1'
!+[]+[]+![]              // 'truefalse'
new Date(0) - 0          // 0
new Date(0) + 0          // 'Thu Jan 01 1970 02:00:00(EET)0'</code></pre><p>Abaixo, você pode encontrar explicações para cada um das expressões.</p><p>O operador binário <code>+</code> causa a conversão para números para <code>true</code> e <code>false</code>:</p><pre><code>true + false
==&gt; 1 + 0
==&gt; 1</code></pre><p>O operador aritmético de divisão <code>/</code> causa a conversão em número para a string <code>'6'</code> :</p><pre><code>12 / '6'
==&gt; 12 / 6
==&gt;&gt; 2</code></pre><p>Abaixo, vemos que o operador <code>+</code> tem associatividade da esquerda para a direita. Assim, a expressão <code>"number" + 15</code> roda primeiro. Como um dos operandos é uma string, o operador <code>+</code> ocasiona a conversão em string para o número <code>15</code>. No segundo passo, a expressão <code>"number15" + 3</code> é avaliada de maneira similar.</p><pre><code>“number” + 15 + 3 
==&gt; "number15" + 3 
==&gt; "number153"</code></pre><p>Aqui, vemos que a expressão <code>15 + 3</code> é avaliada primeiro. Não há necessidade nenhuma de coerção, já que ambos os operandos são números. No segundo passo, a expressão <code>18 + 'number'</code> é avaliada e, como um dos operandos é uma string, isso causa a conversão em string.</p><pre><code>15 + 3 + "number" 
==&gt; 18 + "number" 
==&gt; "18number"</code></pre><p>Neste exemplo, o operador de comparação <code>&amp;gt;</code> ("maior que") ocasiona em conversão para números de <code>[1]</code> e <code>null</code> .</p><pre><code>[1] &gt; null
==&gt; '1' &gt; 0
==&gt; 1 &gt; 0
==&gt; true</code></pre><p>Aqui, vemos que o operador unário <code>+</code> tem maior precedência sobre operador binário <code>+</code>. Assim, a expressão <code>+'bar'</code> é avaliada primeiro. O sinal positivo unário acarreta em conversão em números para a string <code>'bar'</code>. Como a string não representa um número válido, o resultado é <code>NaN</code>. No segundo passo, a expressão <code>'foo' + NaN</code> é avaliada.</p><pre><code>"foo" + + "bar" 
==&gt; "foo" + (+"bar") 
==&gt; "foo" + NaN 
==&gt; "fooNaN"</code></pre><p>Neste exemplo, o operador <code>==</code> acarreta em uma conversão para números, a string <code>'true'</code> é convertida em NaN e o booleano <code>true</code> é convertido em 1.</p><pre><code>'true' == true
==&gt; NaN == 1
==&gt; false

false == 'false'   
==&gt; 0 == NaN
==&gt; false</code></pre><p>Aqui, temos que o operador <code>==</code> geralmente causa a conversão em número, mas esse não é o caso com <code>null</code>. <code>null</code> iguala somente a <code>null</code> ou a <code>undefined</code> e mais nada.</p><pre><code>null == ''
==&gt; false</code></pre><p>O operador <code>!!</code> converte ambas as strings, <code>'true'</code> e<code>'false'</code>, em booleano, já que elas não são strings vazias. Então, <code>==</code> apenas verifica a igualdade de dois booleanos <code>true</code> sem nenhuma coerção.</p><pre><code>!!"false" == !!"true"  
==&gt; true == true
==&gt; true</code></pre><p>O operador <code>==</code> ocasiona em uma conversão em número para um array. O método de arrays <code>valueOf()</code> retorna o próprio array, sendo ignorado porque não é um tipo primitivo. O método de array <code>toString()</code> converte <code>['x']</code> na string <code>'x'</code>.</p><pre><code>['x'] == 'x'  
==&gt; 'x' == 'x'
==&gt;  true</code></pre><p>O operador <code>+</code> acarreta a conversão em número para <code>[]</code>. O método de array <code>valueOf()</code> é ignorado, porque retorna o próprio array, o qual é não primitivo. O método de array <code>toString</code> retorna uma string vazia. </p><p>No segundo passo, a expressão <code>'' + null + 1</code> é avaliada.</p><pre><code>[] + null + 1  
==&gt;  '' + null + 1  
==&gt;  'null' + 1  
==&gt; 'null1'</code></pre><p>Os operadores lógicos <code>||</code> e <code>&amp;&amp;</code> coagem os operandos para booelano, mas retornam os operandos originais (não booleanos). <code>0</code> é falso, enquanto <code>'0'</code> é verdadeiro, porque é uma string não vazia. O objeto vazio <code>{}</code> é também verdadeiro.</p><pre><code>0 || "0" &amp;&amp; {}  
==&gt;  (0 || "0") &amp;&amp; {}
==&gt; (false || true) &amp;&amp; true  // internamente
==&gt; "0" &amp;&amp; {}
==&gt; true &amp;&amp; true             // internamente
==&gt; {}</code></pre><p>Nenhuma coerção é necessária, pois ambos os operandos têm o mesmo tipo. Como <code>==</code> verifica a identidade do objeto (e não sua igualdade) e como os dois arrays são instâncias diferentes, o resultado é <code>false</code>.</p><pre><code>[1,2,3] == [1,2,3]
==&gt;  false</code></pre><p>Todos os operandos são valores não primitivos. Assim, <code>+</code> começa pela esquerda, desencadeando a conversão em número. O método <code>valueOf</code> de <code>Object</code> e de <code>Array</code> retorna o próprio objeto, sendo, então, ignorado. <code>toString()</code> é usado como substituto. O truque aqui é que, primeiro, <code>{}</code> não é considerado um objeto literal, mas uma declaração em bloco, sendo ignorado. A avaliação começa com a próxima expressão <code>+[]</code>, que é convertida em uma string vazia através do método <code>toString()</code> e, então, para <code>0</code> .</p><pre><code>{}+[]+{}+[1]
==&gt; +[]+{}+[1]
==&gt; 0 + {} + [1]
==&gt; 0 + '[object Object]' + [1]
==&gt; '0[object Object]' + [1]
==&gt; '0[object Object]' + '1'
==&gt; '0[object Object]1'</code></pre><p>Este exemplo abaixo é melhor explicado passo a passo de acordo com a precedência de operador.</p><pre><code>!+[]+[]+![]  
==&gt; (!+[]) + [] + (![])
==&gt; !0 + [] + false
==&gt; true + [] + false
==&gt; true + '' + false
==&gt; 'truefalse'</code></pre><p>O operador <code>-</code> acarreta em conversão em números para <code>Date</code>. <code>Date.valueOf()</code> retornando o número de milissegundos desde a <code>epoch</code> do Unix.</p><pre><code>new Date(0) - 0
==&gt; 0 - 0
==&gt; 0</code></pre><p>O operador <code>+</code> acarreta em um conversão padrão. <code>Date</code> assume a conversão em string como padrão. Então, o método <code>toString()</code> é usado em vez de <code>valueOf()</code>.</p><pre><code>new Date(0) + 0
==&gt; 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)' + 0
==&gt; 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'</code></pre><h3 id="recursos-adicionais">Recursos adicionais</h3><p>Eu gostaria de recomendar o excelente livro <a href="https://leanpub.com/understandinges6" rel="noopener"><em>Understanding ES6</em></a>, escrito por Nicholas C. Zakas. É um grande recurso de aprendizado sobre ES6, não muito avançado e que não entra muito nos detalhes.</p><p>Aqui temos um bom livro apenas sobre a ES5 – <a href="http://speakingjs.com/" rel="noopener"><em>SpeakingJS</em></a>, escrito por <a href="https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/undefined" rel="noopener">Axel Rauschmayer</a>.</p><p>(<strong>Russo</strong>) Современный учебник Javascript (Livro didático moderno do JavaScript, em português) — <a href="https://learn.javascript.ru/" rel="noopener">https://learn.javascript.ru/</a>. Em especial, <a href="https://learn.javascript.ru/object-conversion">essas</a> <a href="https://learn.javascript.ru/types-conversion">duas </a>páginas sobre conversão de objetos e de tipo.</p><p>Tabela de comparação do JavaScript — <a href="https://dorey.github.io/JavaScript-Equality-Table/" rel="noopener">https://dorey.github.io/JavaScript-Equality-Table/</a></p><p>wtfjs — um pequeno blog de código sobre essa linguagem que nós amamos, embora nos dê tanta raiva — <a href="https://wtfjs.com/" rel="noopener">https://wtfjs.com/</a></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
