Voltar para o Blog

TypeScript 6.0: Todas as Novidades e Recursos de 2026

Ola HaWkers, o TypeScript 6.0 chegou e traz mudancas significativas que vao impactar como escrevemos codigo. De pattern matching a novos tipos utilitarios, essa versao representa um grande salto na linguagem.

Vamos explorar cada novidade e como usar na pratica.

Pattern Matching Nativo

A Grande Novidade

O recurso mais esperado finalmente chegou: pattern matching nativo no TypeScript.

Sintaxe basica:

// Antes: switch tradicional
function describeValue(value: unknown): string {
  if (typeof value === 'string') {
    return `String: ${value}`;
  } else if (typeof value === 'number') {
    return `Number: ${value}`;
  } else if (Array.isArray(value)) {
    return `Array with ${value.length} items`;
  }
  return 'Unknown';
}

// Agora: Pattern Matching
function describeValue(value: unknown): string {
  return match (value) {
    case string s => `String: ${s}`,
    case number n => `Number: ${n}`,
    case [] => 'Empty array',
    case [first, ...rest] => `Array starting with ${first}`,
    case { name: string n } => `Object with name: ${n}`,
    case _ => 'Unknown'
  };
}

Patterns Avancados

// Pattern matching com tipos customizados
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };

function handleResult<T, E>(result: Result<T, E>): string {
  return match (result) {
    case { ok: true, value: v } => `Success: ${v}`,
    case { ok: false, error: e } => `Error: ${e}`,
  };
}

// Pattern matching com guardas
function processNumber(n: number): string {
  return match (n) {
    case x if x < 0 => 'negative',
    case 0 => 'zero',
    case x if x > 0 && x < 10 => 'small positive',
    case x if x >= 10 && x < 100 => 'medium',
    case _ => 'large'
  };
}

// Pattern matching em arrays
function processArray<T>(arr: T[]): string {
  return match (arr) {
    case [] => 'empty',
    case [single] => `single: ${single}`,
    case [first, second] => `pair: ${first}, ${second}`,
    case [first, second, ...rest] => `many: starts with ${first}, ${second}`
  };
}

// Pattern matching com tipos literais
type Status = 'pending' | 'approved' | 'rejected';

function getStatusMessage(status: Status): string {
  return match (status) {
    case 'pending' => 'Aguardando aprovacao',
    case 'approved' => 'Aprovado com sucesso',
    case 'rejected' => 'Rejeitado'
  };
}

Exaustiveness Checking

// TypeScript garante que todos os casos sao tratados
type Shape =
  | { kind: 'circle'; radius: number }
  | { kind: 'rectangle'; width: number; height: number }
  | { kind: 'triangle'; base: number; height: number };

function calculateArea(shape: Shape): number {
  return match (shape) {
    case { kind: 'circle', radius: r } => Math.PI * r * r,
    case { kind: 'rectangle', width: w, height: h } => w * h,
    case { kind: 'triangle', base: b, height: h } => (b * h) / 2
    // Se adicionar novo tipo a Shape, TypeScript avisa aqui
  };
}

Const Type Parameters

Inferencia Mais Precisa

O novo modificador const para type parameters permite inferencia de tipos literais:

// Antes: tipos eram generalizados
function createConfig<T>(config: T): T {
  return config;
}

const config1 = createConfig({ port: 3000, host: 'localhost' });
// Tipo: { port: number; host: string }

// Agora: com const type parameter
function createConfig<const T>(config: T): T {
  return config;
}

const config2 = createConfig({ port: 3000, host: 'localhost' });
// Tipo: { port: 3000; host: 'localhost' } - tipos literais!

// Util para builders e factories
function defineRoutes<const T extends readonly Route[]>(routes: T): T {
  return routes;
}

const routes = defineRoutes([
  { path: '/home', component: 'Home' },
  { path: '/about', component: 'About' },
] as const);

// Tipo: readonly [
//   { path: '/home'; component: 'Home' },
//   { path: '/about'; component: 'About' }
// ]

Casos de Uso Praticos

// Factory de eventos com tipos precisos
function createEventHandler<const E extends string>(
  event: E,
  handler: (e: CustomEvent<E>) => void
) {
  return { event, handler };
}

const clickHandler = createEventHandler('click', (e) => {
  console.log(e.type); // Tipo: 'click'
});

// Builder de queries com tipos literais
function buildQuery<const T extends QueryDef>(def: T): Query<T> {
  return new Query(def);
}

const query = buildQuery({
  select: ['id', 'name', 'email'],
  from: 'users',
  where: { active: true }
});

// TypeScript sabe exatamente quais campos estao disponiveis
query.results[0].id; // OK
query.results[0].age; // Erro: 'age' nao foi selecionado

Tipos Utilitarios Novos

PartialDeep e RequiredDeep

// PartialDeep: torna todas as propriedades opcionais, recursivamente
type User = {
  id: number;
  profile: {
    name: string;
    address: {
      city: string;
      country: string;
    };
  };
};

// Antes: precisava criar manualmente ou usar biblioteca
// Agora: nativo
type PartialUser = PartialDeep<User>;
// {
//   id?: number;
//   profile?: {
//     name?: string;
//     address?: {
//       city?: string;
//       country?: string;
//     };
//   };
// }

// RequiredDeep: oposto do PartialDeep
type Config = {
  api?: {
    url?: string;
    timeout?: number;
  };
};

type FullConfig = RequiredDeep<Config>;
// {
//   api: {
//     url: string;
//     timeout: number;
//   };
// }

Branded Types Nativos

// Antes: hack com intersecao
type UserId = number & { __brand: 'UserId' };

// Agora: sintaxe nativa
type UserId = branded number;
type OrderId = branded number;
type Email = branded string;

// TypeScript impede mistura
function getUser(id: UserId): User { ... }
function getOrder(id: OrderId): Order { ... }

const userId: UserId = 123 as UserId;
const orderId: OrderId = 456 as OrderId;

getUser(userId); // OK
getUser(orderId); // Erro: OrderId nao e atribuivel a UserId

// Funcao de validacao e branding
function validateEmail(email: string): Email | null {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email) ? (email as Email) : null;
}

const email = validateEmail('user@example.com');
if (email) {
  sendEmail(email); // Tipo garantido
}

Negation Types

// Novo tipo de negacao
type NotNull<T> = T & not null;
type NotUndefined<T> = T & not undefined;
type NotNullish<T> = T & not null & not undefined;

// Util para parametros
function processValue(value: string & not '') {
  // TypeScript garante que value nao e string vazia
  console.log(value.length); // Sempre > 0
}

// Combinacao com unions
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
type ReadOnlyMethod = 'GET';
type WritableMethod = HttpMethod & not ReadOnlyMethod;
// 'POST' | 'PUT' | 'DELETE' | 'PATCH'

Decorators Aprimorados

Decorators de Stage 3

// Decorators agora sao Stage 3 e totalmente tipados

// Decorator de classe
function sealed<T extends new (...args: any[]) => any>(
  target: T,
  context: ClassDecoratorContext<T>
) {
  Object.seal(target);
  Object.seal(target.prototype);
  return target;
}

@sealed
class User {
  constructor(public name: string) {}
}

// Decorator de metodo com tipagem completa
function log<T, A extends any[], R>(
  target: (this: T, ...args: A) => R,
  context: ClassMethodDecoratorContext<T, (this: T, ...args: A) => R>
) {
  return function(this: T, ...args: A): R {
    console.log(`Calling ${String(context.name)} with`, args);
    const result = target.call(this, ...args);
    console.log(`Result:`, result);
    return result;
  };
}

class Calculator {
  @log
  add(a: number, b: number): number {
    return a + b;
  }
}

// Decorator de propriedade
function observable<T, V>(
  target: undefined,
  context: ClassFieldDecoratorContext<T, V>
) {
  return function(this: T, initialValue: V): V {
    let value = initialValue;
    const name = String(context.name);

    Object.defineProperty(this, name, {
      get() { return value; },
      set(newValue: V) {
        console.log(`${name} changed from ${value} to ${newValue}`);
        value = newValue;
      }
    });

    return value;
  };
}

class State {
  @observable
  count = 0;
}

Decorator Metadata

// Novo: metadata de decorators acessivel em runtime

function injectable(target: any, context: ClassDecoratorContext) {
  context.metadata.injectable = true;
  context.metadata.dependencies = Reflect.getMetadata('design:paramtypes', target) || [];
}

function inject(token: string) {
  return function(target: any, context: ClassFieldDecoratorContext) {
    context.metadata.injections = context.metadata.injections || [];
    context.metadata.injections.push({
      field: context.name,
      token
    });
  };
}

@injectable
class UserService {
  @inject('DATABASE')
  private db!: Database;

  @inject('LOGGER')
  private logger!: Logger;
}

// Acessar metadata
const metadata = UserService[Symbol.metadata];
console.log(metadata.injectable); // true
console.log(metadata.injections); // [{ field: 'db', token: 'DATABASE' }, ...]

Inferencia de Tipos Aprimorada

Control Flow Analysis Melhorado

// Inferencia mais inteligente em fluxos complexos

function processData(data: unknown) {
  // TypeScript agora entende narrowing mais complexo
  if (typeof data === 'object' && data !== null) {
    if ('type' in data && data.type === 'user') {
      if ('name' in data && typeof data.name === 'string') {
        // TypeScript infere: { type: 'user'; name: string }
        console.log(data.name.toUpperCase());
      }
    }
  }
}

// Narrowing em closures
function createHandler(value: string | number) {
  if (typeof value === 'string') {
    // TypeScript agora entende que value e string na closure
    return () => value.toUpperCase();
  }
  return () => value.toFixed(2);
}

// Narrowing com predicados de tipo melhorados
function isNonEmpty<T>(arr: T[]): arr is [T, ...T[]] {
  return arr.length > 0;
}

const items: string[] = ['a', 'b', 'c'];
if (isNonEmpty(items)) {
  // TypeScript sabe que items tem pelo menos 1 elemento
  const [first, ...rest] = items; // first: string, rest: string[]
}

Inferencia em Template Literals

// Inferencia mais precisa em template literals

type EventName<T extends string> = `on${Capitalize<T>}`;
type Handler<E extends string> = { [K in EventName<E>]: () => void };

function createHandlers<const E extends readonly string[]>(
  events: E
): Handler<E[number]> {
  const handlers = {} as Handler<E[number]>;
  for (const event of events) {
    const key = `on${event.charAt(0).toUpperCase()}${event.slice(1)}` as EventName<E[number]>;
    handlers[key] = () => console.log(event);
  }
  return handlers;
}

const handlers = createHandlers(['click', 'hover', 'focus']);
// Tipo: { onClick: () => void; onHover: () => void; onFocus: () => void }

handlers.onClick(); // OK
handlers.onScroll(); // Erro: 'onScroll' nao existe

Performance e Compilacao

Compilacao Incremental Melhorada

// tsconfig.json - novas opcoes de performance
{
  "compilerOptions": {
    // Novo: cache de tipos entre compilacoes
    "persistentTypeCache": true,
    "typeCacheDirectory": ".typescript-cache",

    // Novo: paralelizacao de checagem de tipos
    "parallelTypeCheck": true,
    "typeCheckWorkers": 4,

    // Novo: lazy loading de tipos
    "lazyTypeResolution": true,

    // Melhorias existentes
    "incremental": true,
    "tsBuildInfoFile": ".tsbuildinfo",
    "skipLibCheck": true
  }
}

Benchmarks de Performance

Operacao TS 5.x TS 6.0 Melhoria
Build inicial 45s 28s 38%
Build incremental 8s 3s 62%
Watch mode 2s 0.8s 60%
Type checking 30s 18s 40%
Memory usage 2GB 1.4GB 30%

Novo Sistema de Resolucao de Modulos

// tsconfig.json - nova estrategia de resolucao
{
  "compilerOptions": {
    // Novo: resolucao hibrida
    "moduleResolution": "hybrid",

    // Suporta ESM nativo com CJS fallback
    "module": "NodeNext",

    // Novo: resolucao de tipos separada
    "typeResolution": "bundler",

    // Mapeamento de imports mais flexivel
    "imports": {
      "#utils/*": "./src/utils/*.js",
      "#components/*": "./src/components/*.js"
    }
  }
}

// Uso no codigo
import { debounce } from '#utils/helpers';
import { Button } from '#components/Button';

Novos Recursos de Linguagem

Pipe Operator (Experimental)

// Habilitar no tsconfig.json
// "experimentalPipeOperator": true

// Encadeamento fluente de funcoes
const result = value
  |> double
  |> addOne
  |> toString;

// Equivalente a:
const result = toString(addOne(double(value)));

// Com funcoes anonimas
const processed = data
  |> (x => x.filter(item => item.active))
  |> (x => x.map(item => item.name))
  |> (x => x.join(', '));

// Combinando com async
const user = await userId
  |> fetchUser
  |> validateUser
  |> enrichUserData;

Throw Expressions

// Agora e possivel usar throw como expressao

// Em ternarios
const value = condition ? getValue() : throw new Error('Invalid');

// Em nullish coalescing
const config = loadConfig() ?? throw new Error('Config not found');

// Em arrow functions
const assertPositive = (n: number): number =>
  n > 0 ? n : throw new Error('Must be positive');

// Em pattern matching
function processStatus(status: Status): string {
  return match (status) {
    case 'active' => 'Processing...',
    case 'pending' => 'Waiting...',
    case 'unknown' => throw new Error('Unknown status')
  };
}

Using Declarations

// Gerenciamento automatico de recursos

class DatabaseConnection implements Disposable {
  [Symbol.dispose]() {
    console.log('Closing connection');
    this.close();
  }

  close() { /* ... */ }
}

async function processData() {
  using db = new DatabaseConnection();
  // db e automaticamente descartado ao sair do bloco

  const data = await db.query('SELECT * FROM users');
  return data;
} // db.[Symbol.dispose]() chamado aqui

// Com async disposal
class FileHandle implements AsyncDisposable {
  async [Symbol.asyncDispose]() {
    await this.flush();
    await this.close();
  }
}

async function writeFile() {
  await using file = await openFile('output.txt');
  await file.write('Hello, World!');
} // await file.[Symbol.asyncDispose]() chamado aqui

Migracao do TypeScript 5.x

Guia de Atualizacao

# Atualizar TypeScript
npm install typescript@6.0 --save-dev

# Verificar breaking changes
npx tsc --showConfig

# Atualizar gradualmente
npx tsc --build --incremental

Breaking Changes

1. Mudancas em strictness:

// TS 6 e mais estrito com any implicito
const obj = {}; // Agora requer anotacao de tipo se usado como Record

// Correto:
const obj: Record<string, unknown> = {};

2. Decorators legados:

// Decorators experimentais antigos precisam migracao
// tsconfig.json
{
  "compilerOptions": {
    // Remover (deprecated):
    // "experimentalDecorators": true,
    // "emitDecoratorMetadata": true,

    // Agora e padrao:
    "decorators": true
  }
}

3. Module resolution:

// 'node' foi substituido por 'node16' ou 'nodenext'
{
  "compilerOptions": {
    // Antes:
    // "moduleResolution": "node",

    // Agora:
    "moduleResolution": "NodeNext"
  }
}

Checklist de Migracao

  • Atualizar TypeScript para 6.0
  • Revisar tsconfig.json para opcoes deprecadas
  • Migrar decorators legados para novo padrao
  • Atualizar moduleResolution
  • Testar build completo
  • Revisar warnings de tipo
  • Atualizar dependencias de tipos (@types/*)
  • Testar em ambiente de staging

Conclusao

O TypeScript 6.0 traz avancos significativos que tornam a linguagem mais poderosa e expressiva:

Principais novidades:

  1. Pattern matching nativo transforma como escrevemos logica condicional
  2. Const type parameters permitem inferencia mais precisa
  3. Novos tipos utilitarios reduzem boilerplate
  4. Decorators Stage 3 com tipagem completa
  5. Melhorias de performance de 40-60% em compilacao

Recomendacoes:

  • Comece a experimentar em projetos novos
  • Migre gradualmente projetos existentes
  • Aproveite pattern matching para codigo mais limpo
  • Use branded types para seguranca de tipos em dominio

O TypeScript continua evoluindo como a escolha padrao para desenvolvimento JavaScript tipado.

Para mais conteudo sobre TypeScript e JavaScript, leia: Descobrindo o Poder do Async/Await no JavaScript.

Bora pra cima! 🦅

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário