A novidades do TS 5.3
Tags: typescript, development, node, javascript
Published: 2023-10-20 22:27:10

---
title: A novidades do TS 5.3
published: true
date: 2023-08-30 09:00:30 UTC
tags: typescript,development,nodejs,javascript
canonical_url: https://blog.lsantos.dev/ts-53-alpha/
cover_image: https://raw.githubusercontent.com/khaosdoctor/blog-assets/master/images/2023/08/articles-1-1.png
---
Como é de costume, eu quero trazer as principais novidades do TS a medida que elas vão saindo! Recentemente recebi a notícia de que o time do TypeScript está trabalhando em uma [nova versão da linguagem](https://github.com/microsoft/TypeScript/issues/55486), para isso, eles criam o chamado **iteration plan**.

O iteration plan não é um documento que mostra exatamente o que vai sair na linguagem, mas sim o que possivelmente pode estar nas próximas versões. Basicamente é um documento de intenções do time em aplicar e aprimorar o compilador.

A versão beta do TS 5.3 deve sair em setembro (um pouco antes do lançamento do primeiro módulo da [Formação TS](https://formacaots.com.br)) e a versão final deve estar no ar em novembro!

O Matt do Total TypeScript compilou um pouco do que tem no documento nesse [outro artigo](https://www.totaltypescript.com/typescript-5-3), e eu vou aproveitar para poder resumir e explicar também fazendo um link com a documentação do [JavaScript](https://github.com/tc39/proposals).

## Import Attributes

Essa é uma [proposta](https://github.com/tc39/proposal-import-attributes) aberta há um tempo, e o objetivo principal é que você pode especificar algumas opções de validação dos imports de módulos. No momento só estamos falando da validação do tipo do módulo, por exemplo, pra validar que um módulo é um arquivo JSON:

```
import json from './foo.json' with { type: 'json' };
```

Isso é bem útil quando temos a questão de segurança, por exemplo, se um arquivo é esperado para ser JSON mas, na verdade é JS.

Você pode usar esses atributos em imports dinâmicos:

```
import("foo.json", { with: { type: "json" } });
```

Ou até mesmo exportar um módulo com outro tipo validado:

```
export { val } from './foo.js' with { type: "javascript" };
```

Isso também vale para WebAssembly ou workers diferentes:

```
new Worker("foo.wasm", {
  type: "module",
  with: { type: "webassembly" },
});
```

Usar o `with` seguido de `type` é uma forma de deixar essa funcionalidade bem aberta porque será possível incluir mais propriedades depois. Imagina ser possível importar um pacote por uma das propriedades do `package.json` ou então até mesmo do arquivo.

## Throw expressions

Essa é uma funcionalidade que eu vou falar em um futuro vídeo, mas é algo que estava faltando no JS há muito tempo. A [proposta](https://github.com/tc39/proposal-throw-expressions) para isso está ainda no estágio 2, o que é estranho para o TS, que costuma implementar a maioria das funcionalidades quando elas estão no estágio 3.

O que é possível acontecer é que, como eles mencionam no plano, o time vai estar "championing" a proposta, que é uma forma de dizer que eles vão estar ativamente trabalhando nela e empurrando para frente, para fazer chegar mais rápido ao estágio 3 e 4.

A ideia é que você possa usar `throw` fora de algum statement específico, por exemplo, em uma declaração de variável:

```
const userName = user.name || throw new Error('Name is required')
```

Hoje isso não é possível.

## Isolated Declarations

Existe um problema quando se trabalha com monorepos em quase todas as linguagens, porém em TypeScript isso é pior. Porque quando temos pacotes que dependem de outros pacotes, isso acaba invariavelmente gerando uma quantidade absurda de complexidade, principalmente para o TypeScript.

Se você tem 10 níveis de pacotes que dependem entre si, o TS precisa inferir todos os tipos de todos os pacotes ele mesmo, começando de baixo para cima e ir gerando os [arquivos declarativos](https://blog.lsantos.dev/semana-ts-2/) de cada pacote para importar no pacote de cima. E isso é muito lento.

E como não existe uma forma mais rápida de fazer isso sem mudar no compilador, porque outras ferramentas como o esbuild ou até mesmo o swc não são inteligentes o suficientes pra isso, sobra para o TS inferir tudo, e ele não é necessariamente o compilador mais exigente de todos.

Essa [proposta](https://github.com/microsoft/TypeScript/pull/53463) adiciona uma nova configuração no TSConfig chamada `isolatedDeclarations`.

```
{
  "compilerOptions": {
    "isolatedDeclarations": true
  }
}
```

O que ela faz é ativar um modo mais estrito, onde é necessário, por exemplo, colocar anotações de tipo em retorno de funções, principalmente para funções exportadas para fazer o TS não precisar inferir tudo.

## Narrow de generics em funções

Existe um [problema latente](https://github.com/microsoft/TypeScript/issues/33014) no TypeScript que é o fato de que ele não vai fazer um _type narrowing_ em um tipo generico dentro de uma função quando a gente quer retornar algo baseado nesse tipo.

Complicado? Vamos lá. Imagina isso aqui:

```
interface F {
  "t": number,
  "f": boolean,
}

function depLikeFun<T extends "t" | "f">(str: T): F[T] {
  if (str === "t") {
    return 1;
  } else {
    return true;
  }
}

depLikeFun("t"); // number
depLikeFun("f"); // boolean
```

É exatamente isso que estamos falando, o que a gente quer é que, se a gente passar `t`, o tipo de retorno é `number`, se for `f` é `boolean`. Para alcançar esse resultado temos que ter um tipo `T` que é passado como um genérico da função, e depois retornamos a chave da interface `F` baseada em `T`.

Só que se fizermos isso atualmente, vamos ter um erro dizendo que nossos retornos não são do tipo `never`. Isto porque o TS não faz um narrowing do nosso tipo genérico `T`. Na verdade o que ele está fazendo, segundo [essa issue](https://github.com/microsoft/TypeScript/pull/30769), é que quando passamos `F[T]` estamos dizendo "escreva F na chave T", portanto ele vai checar se `F[T]` tem um tipo que intersecta ambas as suas possibilidades (no caso `number` e `boolean`), então `number & boolean` é `never`.

## Autocomplete em tipos de string

Um hack interessante – que eu descobri recentemente – é que você pode criar um _union type_ de strings e `string & {}`, dessa forma você ganha um auto complete do compilador, além de poder colocar qualquer outra string no lugar também:

```
type IconSize =
  | "small"
  | "medium"
  | "large"
  | (string & {});
```

Então isso seria totalmente válido:

```
const icons: IconSize[] = [
  "small",
  "medium",
  "large",
  "extra-large",
];
```

Na versão 5.3 pode ser possível tirar o `& {}` e usar apenas string para obter o mesmo resultado:

```
type IconSize =
  | "small"
  | "medium"
  | "large"
  | string;
```

# O que vem por ai?

Esse é um artigo base, não sabemos se essas funcionalidades serão, de fato, adicionadas ao TS ou não, até porque o documento é um planejamento de trabalho e não um guia do que vai ser incluído por lá.

Espero que algumas dessas funcionalidades, especialmente os unions types e o type narrowing, sejam adicionadas porque vai quebrar um bom galho para a maioria das pessoas.

Além disso, estarei postando as novidades, com exemplos, lá na [comunidade da Formação TS](https://formacaots.com.br) primeiro assim que o TS sair! Então chega mais!