EDNEI
EDNEITRABACH
>Início>Projetos>Experiência>Sobre>Blog
GitHubLinkedInInstagram
status: disponível
>Início>Projetos>Experiência>Sobre>Blog
status: disponível

Conecte-se

Vamos construir algo junto

Sempre interessado em colaborações, problemas interessantes e conversas sobre código, design e tudo mais.

enviar mensagem→

Me encontre também

GitHub
@EdneiTrabach
LinkedIn
/in/edneitrabach
Instagram
@edneitrabach
WhatsApp
Conversar
Desenvolvido com& código

© 2026 EdneiTrabach — All experiments reserved

back to blog
frontend

TypeScript Strict Mode: Padrões para Máxima Produtividade

Como configurar e usar TypeScript strict mode de forma eficaz. Padrões práticos que melhoram a qualidade do código sem sacrificar velocidade de desenvolvimento.

ET

Ednei Trabach

Desenvolvedor Full Stack

20 de dezembro de 202415 min read
#typescript#patterns#vuejs#react

Por que Strict Mode?

TypeScript strict mode ativa todas as verificações de tipo mais rigorosas. Embora pareça mais trabalho no início, paga dividendos enormes em manutenibilidade e prevenção de bugs.

Configuração

tsconfig.json

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Padrões Práticos

1. Tipos Explícitos em Fronteiras

// ✅ Bom: Tipos explícitos em funções públicas
interface UserProfile {
  id: string
  name: string
  email: string
  preferences: UserPreferences
}

async function getUserProfile(userId: string): Promise<UserProfile> {
  const response = await fetch(`/api/users/${userId}`)
  return response.json()
}

// ❌ Ruim: any implicit
async function getUserProfile(userId: string) {
  const response = await fetch(`/api/users/${userId}`)
  return response.json() // Retorna any
}

2. Type Guards Seguros

// Type guard para discriminar tipos
function isUserProfile(value: unknown): value is UserProfile {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    'name' in value &&
    'email' in value
  )
}

// Uso seguro
if (isUserProfile(data)) {
  console.log(data.name) // TypeScript sabe que é UserProfile
}

3. Utility Types

// Partial para formulários
interface User {
  name: string
  email: string
  age: number
}

type UserForm = Partial<User>

// Pick para selecionar campos
type UserPreview = Pick<User, 'name' | 'email'>

// Omit para excluir campos
type CreateUser = Omit<User, 'id'>

// Required para tornar tudo obrigatório
type CompleteUser = Required<Partial<User>>

4. Genéricos Reutilizáveis

// Hook genérico
function useQuery<T>(
  queryFn: () => Promise<T>,
  options?: { enabled?: boolean }
) {
  const [data, setData] = useState<T | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<Error | null>(null)

  const fetch = async () => {
    if (options?.enabled === false) return

    setLoading(true)
    try {
      const result = await queryFn()
      setData(result)
    } catch (err) {
      setError(err as Error)
    } finally {
      setLoading(false)
    }
  }

  return { data, loading, error, refetch: fetch }
}

// Uso
const { data: user } = useQuery(() => getUserProfile('123'))
const { data: posts } = useQuery(() => getUserPosts('123'))

5. Type Narrowing

function processValue(value: string | number) {
  if (typeof value === 'string') {
    return value.toUpperCase() // TypeScript sabe que é string
  }
  return value * 2 // TypeScript sabe que é number
}

// Discriminated unions
type SuccessResponse = {
  status: 'success'
  data: UserProfile
}

type ErrorResponse = {
  status: 'error'
  error: string
}

type ApiResponse = SuccessResponse | ErrorResponse

function handleResponse(response: ApiResponse) {
  if (response.status === 'success') {
    return response.data // TypeScript sabe que tem data
  }
  throw new Error(response.error) // TypeScript sabe que tem error
}

6. Null Assertions com Cuidado

// ❌ Evitar quando possível
const element = document.getElementById('app')!
element.classList.add('active')

// ✅ Melhor: verificar
const element = document.getElementById('app')
if (element) {
  element.classList.add('active')
}

// ✅ Use quando você tem certeza
const user = getUser() // Sempre retorna usuário
user.email // Seguro usar

Padrões Vue.js + TypeScript

Composables Tipados

// useCounter.ts
import { ref, computed, type Ref } from 'vue'

export function useCounter(initialValue: number = 0) {
  const count: Ref<number> = ref(initialValue)
  const doubleCount = computed(() => count.value * 2)

  const increment = () => count.value++
  const decrement = () => count.value--
  const reset = () => count.value = initialValue

  return {
    count,
    doubleCount,
    increment,
    decrement,
    reset
  }
}

Props Tipadas

<script setup lang="ts">
interface Props {
  title: string
  count?: number
  user: {
    name: string
    email: string
  }
}

const props = withDefaults(defineProps<Props>(), {
  count: 0
})
</script>

Padrões React + TypeScript

Hooks Tipados

import { useState, useEffect } from 'react'

interface User {
  id: string
  name: string
}

function useUser(userId: string) {
  const [user, setUser] = useState<User | null>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetchUser(userId).then(setUser).finally(() => setLoading(false))
  }, [userId])

  return { user, loading }
}

Ferramentas Úteis

ESLint + TypeScript

{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking"
  ],
  "rules": {
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/explicit-function-return-type": "warn",
    "@typescript-eslint/no-unused-vars": "error"
  }
}

Conclusão

TypeScript strict mode não é sobre ser mais lento - é sobre ser mais rápido prevenindo bugs. Na minha experiência, o investimento inicial em configuração rigorosa se paga 10x em manutenibilidade e velocidade de refatoração.

Comece com strict mode ativado. A curva de aprendizado é real, mas os benefícios são duradouros.

share
share:
[RELATED_POSTS]

Continue Reading

frontend

Vue.js: Composition API vs Options API - Qual Escolher?

Uma análise prática comparando Composition API e Options API no Vue.js 3. Quando usar cada abordagem e como elas impactam a organização do código.

15 de janeiro de 2025•8 min read
frontend

Construindo PWAs com Vue.js 3: Experiência Offline Real

Guia prático para criar Progressive Web Apps com Vue.js 3, Vite e Workbox. Transformando aplicações web em experiências nativas.

15 de dezembro de 2024•12 min read