# Suporte ao TypeScript

O Vue CLI (opens new window) fornece ferramentas integradas de suporte ao TypeScript.

# Declaração Oficial em Pacotes NPM

Um sistema de tipagem estática pode ajudar à prevenir diversos potenciais erros de runtime conforme as aplicações crescem, é por isso que o Vue 3 é escrito em TypeScript. Isso significa que você não precisa de nenhum ferramental adicional para usar TypeScript com Vue - temos um suporte de primeiro mundo.

# Configuração Recomendada

// tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    // isso permite uma inferência mais estrita para propriedades de dados no `this`
    "strict": true,
    "jsx": "preserve",
    "moduleResolution": "node"
  }
}
1
2
3
4
5
6
7
8
9
10
11

Observe que você precisa incluir strict: true (ou ao menos noImplicitThis: true, que é uma parte da flag strict) para aumentar a checagem de tipos do this em métodos de componentes, caso contrário, será sempre tratado como tipo any.

Veja a documentação das opções do compilador TypeScript (opens new window) para mais detalhes.

# Ferramentas de Desenvolvimento

# Criação de Projeto

O Vue CLI (opens new window) pode gerar novos projetos que usam TypeScript. Para começar:

# 1. Instale o Vue CLI, se não estiver instalado
npm install --global @vue/cli

# 2. Crie um novo projeto e então escolha a opção "Manually select features"
vue create my-project-name

# Se você já tem um projeto com Vue CLI sem TypeScript, por favor adicione o plugin apropriado:
vue add typescript
1
2
3
4
5
6
7
8

Certifique-se que a parte script do componente tem o TypeScript definido como linguagem:

<script lang="ts">
  ...
</script>
1
2
3

# Suporte do Editor

Para o desenvolvimento de aplicações Vue com TypeScript, nós recomendamos fortemente o uso do Visual Studio Code (opens new window), que fornece um excelente suporte para o TypeScript. Se você está usando componentes Single File (SFCs), obtenha a incrível extensão Vetur (opens new window), que provê a inferência do TypeScript dentro de SFCs e muitos outros ótimos recursos.

O WebStorm (opens new window) também fornece um suporte pronto para uso de ambos, TypeScript e Vue.

# Definindo Componentes Vue

Para permitir ao TypeScript inferir corretamente os tipos dentro das opções do componente Vue, você precisa definir os componentes com o método global defineComponent:

import { defineComponent } from 'vue'

const Component = defineComponent({
  // inferência de tipos habilitada
})
1
2
3
4
5

# Usando a API de Opções

O TypeScript deve ser capaz de inferir a maioria dos tipos sem defini-los explicitamente. Por exemplo, se você tem um componente com uma propriedade numérica count, você receberá um erro se tentar chamar um método específico de string nela.

const Component = defineComponent({
  data() {
    return {
      count: 0
    }
  },
  mounted() {
    const result = this.count.split('') // => A propriedade 'split' não existe no tipo 'number'
  }
})
1
2
3
4
5
6
7
8
9
10

Se você tem um tipo complexo ou uma interface, pode convertê-lo(a) usando a afirmação de tipo (opens new window):

interface Book {
  title: string
  author: string
  year: number
}

const Component = defineComponent({
  data() {
    return {
      book: {
        title: 'Vue 3 Guide',
        author: 'Vue Team',
        year: 2020
      } as Book
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Anotando Tipos de Retorno

Por causa da natureza circular dos arquivos de declaração do Vue, o TypeScript pode ter dificuldades para inferir os tipos de dados computados. Por esse motivo, você precisa anotar o tipo do retorno de propriedades computadas.

import { defineComponent } from 'vue'

const Component = defineComponent({
  data() {
    return {
      message: 'Hello!'
    }
  },
  computed: {
    // precisa de uma anotação
    greeting(): string {
      return this.message + '!'
    }

    // em uma computada com um setter, o getter precisa ser anotado
    greetingUppercased: {
      get(): string {
        return this.greeting.toUpperCase();
      },
      set(newValue: string) {
        this.message = newValue.toUpperCase();
      },
    },
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Anotando Propriedades

O Vue faz uma validação em runtime em propriedades com um type definido. Para fornecer esses tipos para o TypeScript, precisamos converter o construtor com PropType:

import { defineComponent, PropType } from 'vue'

interface ComplexMessage {
  title: string
  okMessage: string
  cancelMessage: string
}
const Component = defineComponent({
  props: {
    name: String,
    success: { type: String },
    callback: {
      type: Function as PropType<() => void>
    },
    message: {
      type: Object as PropType<ComplexMessage>,
      required: true,
      validator(message: ComplexMessage) {
        return !!message.title
      }
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Se você descobrir que o validador não está obtendo a inferência de tipo ou a conclusão do membro não está funcionando, anotar o argumento com o tipo esperado pode ajudar a resolver esse problema.

# Usando com a API de Composição

Na função setup(), você não precisa passar um tipo para o parâmetro props, pois os tipos serão inferidos da opção props do componente.

import { defineComponent } from 'vue'

const Component = defineComponent({
  props: {
    message: {
      type: String,
      required: true
    }
  },

  setup(props) {
    const result = props.message.split('') // correto, 'message' é tipada como uma string
    const filtered = props.message.filter(p => p.value) // um erro será disparado: Propriedade 'filter' não existe no tipo 'string'
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Tipando refs

Refs inferem o tipo do valor inicial:

import { defineComponent, ref } from 'vue'

const Component = defineComponent({
  setup() {
    const year = ref(2020)

    const result = year.value.split('') // => Propriedade 'split' não existe no tipo 'number'
  }
})
1
2
3
4
5
6
7
8
9

Algumas vezes, podemos precisar especificar tipos complexos para o valor interno de uma ref. Podemos fazer isso simplesmente passando um argumento genérico ao chamar ref para sobrescrever a inferência padrão:

const year = ref<string | number>('2020') // tipo do year: Ref<string | number>

year.value = 2020 // ok!
1
2
3

Nota

Se o tipo do genérico é desconhecido, é recomendado converter ref para Ref<T>.

# Tipando reactive

Ao tipar uma propriedade reactive, podemos usar interfaces:

import { defineComponent, reactive } from 'vue'

interface Book {
  title: string
  year?: number
}

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const book = reactive<Book>({ title: 'Vue 3 Guide' })
    // ou
    const book: Book = reactive({ title: 'Vue 3 Guide' })
    // ou
    const book = reactive({ title: 'Vue 3 Guide' }) as Book
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Tipando computed

Valores computados irão inferir automaticamente o tipo do valor retornado

import { defineComponent, ref, computed } from 'vue'

export default defineComponent({
  name: 'CounterButton',
  setup() {
    let count = ref(0)

    // apenas leitura
    const doubleCount = computed(() => count.value * 2)

    const result = doubleCount.value.split('') // => Propriedade 'split' não existe no tipo 'number'
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13

Deployed on Netlify.
Atualizado pela última vez: 10/15/2020, 2:50:19 PM