# 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"
}
}
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
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>
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
})
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'
}
})
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
}
}
})
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();
},
},
}
})
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
}
}
}
})
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'
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Tipando ref
s
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'
}
})
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!
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
}
})
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'
}
})
2
3
4
5
6
7
8
9
10
11
12
13