TypeScript se tornou o padrão para o desenvolvimento moderno de JavaScript. Em 2026, mais de 80% dos novos projetos JavaScript usam TypeScript. Este guia completo cobre tudo, desde tipos básicos até genéricos avançados, decoradores e padrões de produção.
📋 Table of Contents
- Por que TypeScript em 2026?
- Instalação e configuração
- Práticas recomendadas de tsconfig.json
- Tipos Básicos
- Interfaces versus tipos
- Genéricos
- Tipos de utilitários
- Padrões Avançados: Tipos Condicionais
- TypeScript com React
- Decoradores TypeScript (2026)
- Lista de verificação do modo estrito
- Ferramentas TypeScript em 2026
- Principais conclusões
Por que TypeScript em 2026?
A natureza dinâmica do JavaScript causa erros de tempo de execução que o TypeScript detecta em tempo de compilação. Os benefícios são claros:
- Detecte bugs cedo— erros de tipo em tempo de compilação, não em produção
- Melhores ferramentas— preenchimento automático, refatoração e navegação no VS Code
- Código autodocumentado— tipos servem como documentação inline
- Confiança em grande escala— refatoração segura em milhares de arquivos
Instalação e configuração
Instale o TypeScript globalmente ou como uma dependência de desenvolvimento:
# Install TypeScript
npm install -g typescript
# Or as dev dependency
npm install --save-dev typescript
# Check version
tsc --version
# Initialize tsconfig
tsc --init
Práticas recomendadas de tsconfig.json
Pronto para produçãotsconfig.jsonpara 2026:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"lib": ["ES2022", "DOM"],
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Tipos Básicos
O sistema de tipos do TypeScript começa com primitivos e aumenta:
// Primitives
const name: string = "Alice";
const age: number = 30;
const active: boolean = true;
const nothing: null = null;
const unknown: undefined = undefined;
// Arrays
const scores: number[] = [95, 87, 92];
const tags: Array<string> = ["ts", "js", "node"];
// Tuples (fixed-length arrays with known types)
const point: [number, number] = [10, 20];
const entry: [string, number] = ["age", 30];
// Union types
let id: string | number = "user_123";
id = 456; // also valid
// Literal types
type Direction = "north" | "south" | "east" | "west";
const dir: Direction = "north";
// any, unknown, never
const userInput: unknown = getUserInput();
if (typeof userInput === "string") {
console.log(userInput.toUpperCase()); // type narrowed to string
}
Interfaces versus tipos
Ambos definem formas de objetos, mas com diferenças importantes:
// Interface — can be merged (declaration merging)
interface User {
id: number;
name: string;
email?: string; // optional
}
// Extend interface
interface AdminUser extends User {
role: "admin" | "superadmin";
permissions: string[];
}
// Type alias — more flexible, supports unions and intersections
type ApiResponse<T> = {
data: T;
error: string | null;
status: number;
};
// Intersection type
type AuthUser = User & { token: string };
// Prefer interface for object shapes, type for unions/intersections
const user: AdminUser = {
id: 1,
name: "Alice",
role: "admin",
permissions: ["read", "write"]
};
Genéricos
Os genéricos tornam o código reutilizável e ao mesmo tempo mantêm a segurança do tipo:
// Generic function
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const num = first([1, 2, 3]); // type: number | undefined
const str = first(["a", "b"]); // type: string | undefined
// Generic with constraints
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 1, name: "Alice", age: 30 };
const name = getProperty(user, "name"); // type: string
const id = getProperty(user, "id"); // type: number
// Generic interface
interface Repository<T> {
findById(id: number): Promise<T | null>;
findAll(): Promise<T[]>;
create(item: Omit<T, "id">): Promise<T>;
update(id: number, item: Partial<T>): Promise<T>;
delete(id: number): Promise<void>;
}
// Generic class
class Stack<T> {
private items: T[] = [];
push(item: T): void { this.items.push(item); }
pop(): T | undefined { return this.items.pop(); }
peek(): T | undefined { return this.items[this.items.length - 1]; }
isEmpty(): boolean { return this.items.length === 0; }
}
const stack = new Stack<number>();
stack.push(1);
stack.push(2);
console.log(stack.pop()); // 2
Tipos de utilitários
O TypeScript vem com poderosos tipos de utilitários integrados:
interface Product {
id: number;
name: string;
price: number;
description: string;
inStock: boolean;
}
// Partial — all fields optional
type ProductDraft = Partial<Product>;
// Required — all fields required
type FullProduct = Required<Product>;
// Pick — select specific fields
type ProductSummary = Pick<Product, "id" | "name" | "price">;
// Omit — exclude fields
type NewProduct = Omit<Product, "id">;
// Readonly — prevent mutation
type ImmutableProduct = Readonly<Product>;
// Record — map type
type CategoryMap = Record<string, Product[]>;
// ReturnType — extract function return type
async function fetchUser() {
return { id: 1, name: "Alice", email: "alice@example.com" };
}
type User = Awaited<ReturnType<typeof fetchUser>>;
// Parameters — extract function parameters
function createOrder(userId: number, items: string[], total: number) {}
type OrderParams = Parameters<typeof createOrder>;
Padrões Avançados: Tipos Condicionais
// Conditional type
type IsArray<T> = T extends any[] ? true : false;
type A = IsArray<string[]>; // true
type B = IsArray<string>; // false
// Infer keyword
type UnpackArray<T> = T extends (infer U)[] ? U : T;
type Unpacked = UnpackArray<string[]>; // string
type NotArray = UnpackArray<number>; // number
// Mapped types
type Optional<T> = {
[K in keyof T]?: T[K];
};
// Template literal types (TypeScript 4.1+)
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"
type FocusEvent = EventName<"focus">; // "onFocus"
// Discriminated unions
type Result<T> =
| { success: true; data: T }
| { success: false; error: string };
function processResult<T>(result: Result<T>): T {
if (result.success) {
return result.data; // TypeScript knows this is T
}
throw new Error(result.error); // TypeScript knows error is string
}
TypeScript com React
import React, { useState, useCallback, FC } from "react";
interface ButtonProps {
label: string;
onClick: () => void;
variant?: "primary" | "secondary" | "danger";
disabled?: boolean;
children?: React.ReactNode;
}
const Button: FC<ButtonProps> = ({
label,
onClick,
variant = "primary",
disabled = false,
children
}) => {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
disabled={disabled}
>
{children ?? label}
</button>
);
};
// Generic component
interface ListProps<T> {
items: T[];
renderItem: (item: T, index: number) => React.ReactNode;
keyExtractor: (item: T) => string | number;
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map((item, index) => (
<li key={keyExtractor(item)}>{renderItem(item, index)}</li>
))}
</ul>
);
}
// Custom hook with types
function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
const setStoredValue = useCallback((newValue: T) => {
setValue(newValue);
localStorage.setItem(key, JSON.stringify(newValue));
}, [key]);
return [value, setStoredValue] as const;
}
Decoradores TypeScript (2026)
TypeScript 5.0+ suporta decoradores de Estágio 3:
// Class decorator
function singleton<T extends { new(...args: any[]): {} }>(constructor: T) {
let instance: T;
return class extends constructor {
constructor(...args: any[]) {
if (instance) return instance;
super(...args);
instance = this as any;
}
};
}
// Method decorator — log execution time
function measure(_target: any, key: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = async function (...args: any[]) {
const start = performance.now();
const result = await original.apply(this, args);
const duration = performance.now() - start;
console.log(`${key} took ${duration.toFixed(2)}ms`);
return result;
};
return descriptor;
}
class UserService {
@measure
async fetchUsers(): Promise<User[]> {
const r = await fetch("/api/users");
return r.json();
}
}
Lista de verificação do modo estrito
Habilite estas opções do compilador para máxima segurança de tipo:
strict: true— permite todas as verificações rigorosasnoUncheckedIndexedAccess: true– retornos de acesso ao arrayT | undefinedexactOptionalPropertyTypes: true—undefinednão atribuível a opcionalnoImplicitOverride: true– deve usaroverridepalavra-chavenoPropertyAccessFromIndexSignature: true– use notação de colchetes para assinaturas de índice
Ferramentas TypeScript em 2026
- Bioma– linter + formatador mais rápido, nativo de TypeScript
- tsx— execute arquivos TypeScript diretamente sem compilar
- tsup— empacotador zero-config para bibliotecas TypeScript
- Teste— Primeiros testes de TypeScript com ESM nativo
- tRPC— segurança de ponta a ponta para aplicativos full-stack
Principais conclusões
TypeScript em 2026 é maduro, rápido e essencial para o desenvolvimento profissional de JavaScript. Comece comstrict: true, use interfaces para formatos de objetos, apoie-se em tipos de utilitários e aproveite genéricos para código reutilizável. O ecossistema de ferramentas nunca foi melhor.
🔗 Share this article
✍️ Leave a Comment