Voltar para o Blog

ES2026: Os Novos Recursos Que Vao Transformar o JavaScript

Ola HaWkers, 2026 promete ser um ano historico para o JavaScript. O ECMAScript 2026 esta trazendo algumas das mudancas mais esperadas da historia da linguagem, incluindo a tao aguardada Temporal API que finalmente vai aposentar o objeto Date.

Vamos explorar os principais recursos que estao chegando e como eles vao impactar seu codigo no dia a dia.

Temporal API

Adeus Date, Ola Temporal

Depois de anos de desenvolvimento, a Temporal API finalmente chega ao JavaScript.

Problemas do Date que Temporal resolve:

Problema do Date Solucao do Temporal
Mutavel Imutavel por padrao
Meses 0-indexados Meses 1-indexados
Sem suporte a timezones Suporte completo
Parsing inconsistente Parsing previsivel
Sem duracao nativa Duration como tipo

Tipos principais do Temporal:

// Temporal.PlainDate - Data sem tempo ou timezone
const date = Temporal.PlainDate.from('2026-01-22');
console.log(date.year);  // 2026
console.log(date.month); // 1 (nao 0!)
console.log(date.day);   // 22

// Temporal.PlainTime - Hora sem data ou timezone
const time = Temporal.PlainTime.from('14:30:00');
console.log(time.hour);   // 14
console.log(time.minute); // 30

// Temporal.PlainDateTime - Data e hora sem timezone
const dateTime = Temporal.PlainDateTime.from('2026-01-22T14:30:00');

// Temporal.ZonedDateTime - Data e hora COM timezone
const zonedDateTime = Temporal.ZonedDateTime.from({
  year: 2026,
  month: 1,
  day: 22,
  hour: 14,
  minute: 30,
  timeZone: 'America/Sao_Paulo'
});

// Temporal.Instant - Ponto exato no tempo (como Unix timestamp)
const instant = Temporal.Instant.from('2026-01-22T17:30:00Z');

Operacoes Com Temporal

O que torna Temporal realmente poderoso sao as operacoes.

Aritmetica de datas:

// Adicionar/subtrair com imutabilidade
const hoje = Temporal.PlainDate.from('2026-01-22');

// Adicionar 30 dias (retorna NOVA instancia)
const emUmMes = hoje.add({ days: 30 });
console.log(emUmMes.toString()); // 2026-02-21

// Subtrair 1 ano
const anoPassado = hoje.subtract({ years: 1 });
console.log(anoPassado.toString()); // 2025-01-22

// Operacoes encadeadas
const futuro = hoje
  .add({ months: 3 })
  .add({ days: 15 })
  .subtract({ weeks: 1 });

Diferencas entre datas:

const inicio = Temporal.PlainDate.from('2026-01-01');
const fim = Temporal.PlainDate.from('2026-12-31');

// Calcular diferenca
const diferenca = inicio.until(fim);
console.log(diferenca.toString()); // P364D (364 dias em ISO 8601)

// Com unidades especificas
const diferencaDetalhada = inicio.until(fim, {
  largestUnit: 'month'
});
console.log(diferencaDetalhada.months); // 11
console.log(diferencaDetalhada.days);   // 30

Comparacoes:

const data1 = Temporal.PlainDate.from('2026-01-22');
const data2 = Temporal.PlainDate.from('2026-06-15');

// Comparacao direta
console.log(Temporal.PlainDate.compare(data1, data2)); // -1 (data1 < data2)

// Metodos de comparacao
console.log(data1.equals(data2));  // false
console.log(data1.since(data2));   // -P145D (145 dias atras)

Temporal.Duration

Um tipo dedicado para representar duracoes de tempo.

// Criar duracao
const duracao = Temporal.Duration.from({
  hours: 2,
  minutes: 30,
  seconds: 45
});

// Ou de string ISO 8601
const duracaoISO = Temporal.Duration.from('PT2H30M45S');

// Operacoes com duracao
const duracaoTotal = duracao.add({ minutes: 15 });
console.log(duracaoTotal.toString()); // PT2H45M45S

// Calcular total em uma unidade
const totalMinutos = duracao.total({ unit: 'minute' });
console.log(totalMinutos); // 150.75

// Arredondar duracao
const arredondada = duracao.round({
  smallestUnit: 'minute',
  roundingMode: 'ceil'
});
console.log(arredondada.toString()); // PT2H31M

Uso pratico - Timer de aplicacao:

class TaskTimer {
  #startInstant = null;
  #pausedDuration = Temporal.Duration.from({ seconds: 0 });

  start() {
    this.#startInstant = Temporal.Now.instant();
  }

  pause() {
    if (this.#startInstant) {
      const elapsed = this.#startInstant.until(Temporal.Now.instant());
      this.#pausedDuration = this.#pausedDuration.add(elapsed);
      this.#startInstant = null;
    }
  }

  getElapsed() {
    let total = this.#pausedDuration;

    if (this.#startInstant) {
      const current = this.#startInstant.until(Temporal.Now.instant());
      total = total.add(current);
    }

    return total.round({ smallestUnit: 'second' });
  }

  format() {
    const elapsed = this.getElapsed();
    const hours = String(elapsed.hours).padStart(2, '0');
    const minutes = String(elapsed.minutes).padStart(2, '0');
    const seconds = String(elapsed.seconds).padStart(2, '0');
    return `${hours}:${minutes}:${seconds}`;
  }
}

const timer = new TaskTimer();
timer.start();
// ... trabalhar na task
console.log(timer.format()); // "01:23:45"

Iterator Helpers

Iterator.concat e Mais

ES2026 traz helpers poderosos para trabalhar com iterators.

Iterator.concat:

// Concatenar multiplos iterables
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const set = new Set([7, 8, 9]);

const combined = Iterator.concat(array1, array2, set);

for (const value of combined) {
  console.log(value); // 1, 2, 3, 4, 5, 6, 7, 8, 9
}

// Converter para array
const asArray = [...Iterator.concat(array1, array2)];
console.log(asArray); // [1, 2, 3, 4, 5, 6]

Iterator helpers ja disponiveis:

// map, filter, take, drop - agora nativos em iterators
function* numeros() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
}

// Encadear operacoes de forma lazy
const resultado = numeros()
  .filter(n => n % 2 === 0)  // [2, 4]
  .map(n => n * 10)          // [20, 40]
  .take(1);                   // [20]

console.log([...resultado]); // [20]

// Sem criar arrays intermediarios!

Uso pratico - Paginacao lazy:

async function* fetchPages(baseUrl) {
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const response = await fetch(`${baseUrl}?page=${page}`);
    const data = await response.json();

    yield* data.items;

    hasMore = data.hasNextPage;
    page++;
  }
}

// Consumir apenas os primeiros 10 itens
// Mesmo que haja 1000 paginas
const first10 = await Array.fromAsync(
  fetchPages('/api/users').take(10)
);

Promise.try

Unificando Codigo Sincrono e Assincrono

Um helper simples mas poderoso para tratamento de erros.

// Problema: funcao pode ser sync ou async
function processData(data) {
  if (!data) {
    throw new Error('Data required'); // Sync throw
  }
  return fetchProcessedData(data);    // Async
}

// Antes: precisava de try/catch E .catch()
async function oldWay(data) {
  try {
    return await processData(data);
  } catch (error) {
    console.error(error);
  }
}

// Agora: Promise.try unifica tudo
Promise.try(() => processData(data))
  .then(result => console.log(result))
  .catch(error => console.error(error)); // Pega sync E async errors

Uso com async/await:

// Funcao que pode falhar de forma sync ou async
function parseAndFetch(jsonString) {
  const config = JSON.parse(jsonString); // Pode falhar sync
  return fetch(config.url);              // Async
}

// Promise.try garante que erros sync viram rejeicoes
const result = await Promise.try(() => parseAndFetch(userInput))
  .catch(error => {
    // Trata tanto JSON.parse error quanto fetch error
    return { error: error.message };
  });

Decorators (Stage 3)

Metaprogramacao Padronizada

Decorators finalmente estao se estabilizando.

// Decorator de classe
function logged(target, context) {
  if (context.kind === 'method') {
    return function (...args) {
      console.log(`Calling ${context.name} with`, args);
      const result = target.apply(this, args);
      console.log(`${context.name} returned`, result);
      return result;
    };
  }
}

// Decorator de validacao
function validate(schema) {
  return function (target, context) {
    return function (...args) {
      const errors = schema.validate(args);
      if (errors.length) {
        throw new Error(`Validation failed: ${errors.join(', ')}`);
      }
      return target.apply(this, args);
    };
  };
}

class UserService {
  @logged
  @validate(userSchema)
  createUser(name, email) {
    return { id: crypto.randomUUID(), name, email };
  }

  @logged
  async findUser(id) {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
  }
}

const service = new UserService();
service.createUser('Jeff', 'jeff@example.com');
// Console: Calling createUser with ['Jeff', 'jeff@example.com']
// Console: createUser returned { id: '...', name: 'Jeff', email: '...' }

Record e Tuple (Stage 2)

Estruturas Imutaveis Nativas

Ainda em desenvolvimento, mas promissores.

// Record - objeto imutavel
const user = #{ name: 'Jeff', age: 30 };

// Comparacao por valor, nao referencia!
const user2 = #{ name: 'Jeff', age: 30 };
console.log(user === user2); // true!

// Tuple - array imutavel
const coords = #[10, 20, 30];
const coords2 = #[10, 20, 30];
console.log(coords === coords2); // true!

// Podem ser usados como chaves de Map
const cache = new Map();
cache.set(#{ x: 10, y: 20 }, 'Point A');
cache.get(#{ x: 10, y: 20 }); // 'Point A' - funciona!

// Spread cria novo record/tuple
const updatedUser = #{ ...user, age: 31 };
console.log(user.age);        // 30 (original intacto)
console.log(updatedUser.age); // 31

Math Improvements

Novos Metodos Matematicos

Operacoes matematicas que faltavam.

// Math.sumPrecise - soma sem perda de precisao
const numbers = [0.1, 0.2, 0.3, 0.4];
console.log(numbers.reduce((a, b) => a + b)); // 0.9999999999999999
console.log(Math.sumPrecise(numbers));        // 1

// Util para calculos financeiros
const prices = [19.99, 29.99, 9.99, 14.99];
const total = Math.sumPrecise(prices);
console.log(total); // 74.96 (exato!)

// Math.clamp - limitar valor a um range
const value = 150;
console.log(Math.clamp(value, 0, 100)); // 100

const negative = -50;
console.log(Math.clamp(negative, 0, 100)); // 0

// Uso pratico - volume de audio
function setVolume(level) {
  return Math.clamp(level, 0, 1);
}

// Math.scale - mapear valor de um range para outro
// Equivalente a: ((value - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin
const celsius = 25;
const fahrenheit = Math.scale(celsius, 0, 100, 32, 212);
console.log(fahrenheit); // 77

Migracao Gradual

Como Adotar ES2026

Estrategias para comecar a usar os novos recursos.

Verificando suporte:

// Temporal
if (typeof Temporal !== 'undefined') {
  // Usar Temporal
} else {
  // Fallback para Date ou polyfill
}

// Feature detection para iterators
if (typeof Iterator !== 'undefined' && Iterator.concat) {
  // Usar Iterator.concat
} else {
  // Fallback
}

Polyfills recomendados:

# Temporal polyfill
npm install @js-temporal/polyfill

# Iterator helpers polyfill
npm install core-js

Configuracao Babel/TypeScript:

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: '> 0.25%, not dead',
      useBuiltIns: 'usage',
      corejs: 3
    }]
  ]
};

// tsconfig.json
{
  "compilerOptions": {
    "lib": ["ES2026", "DOM"],
    "target": "ES2022"
  }
}

Conclusao

ES2026 representa uma das maiores evolucoes do JavaScript em anos. A Temporal API sozinha ja justificaria a atualizacao, mas os iterator helpers, Promise.try e outros recursos tornam esta versao ainda mais significativa.

Pontos principais:

  1. Temporal API finalmente resolve os problemas do Date
  2. Iterator helpers trazem operacoes lazy nativas
  3. Promise.try unifica tratamento de erros sync/async
  4. Decorators padronizados estao proximos
  5. Record/Tuple prometem imutabilidade nativa

Recomendacoes:

  • Comece a aprender Temporal API agora
  • Use polyfills para experimentar em producao
  • Atualize suas ferramentas de build
  • Migre gradualmente do Date para Temporal
  • Aproveite iterator helpers para codigo mais limpo

Para entender mais sobre as tendencias do JavaScript, leia: JavaScript Frameworks: O Que Esperar em 2026.

Bora pra cima! 🦅

Comentários (0)

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

Adicionar comentário