Skip to content

Instantly share code, notes, and snippets.

@reginadiana
Last active September 3, 2023 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reginadiana/c92609d5e31b152351d1d8d49d3fa5c1 to your computer and use it in GitHub Desktop.
Save reginadiana/c92609d5e31b152351d1d8d49d3fa5c1 to your computer and use it in GitHub Desktop.
Anotações sobre Typescript

⭐ Typescript

É um recurso desenvolvido pela empresa Microsoft em 2012, sendo ele um superconjunto de recursos já existentes no javascript que seriam bem complexos de se desenvolver nativamente. Como:

❤️ Tipagem explicita, ou seja, todos os tipos são e devem ser declarados no código;

❤️ Orientação a objetos

❤️ Permitir que sites e aplicativos sejam executados tanto no lado do cliente como no servidor com o Node.js

❤️ O código em typescript é tranformado (transcompilado) para javascript puro antes de ser executado pelo navegador.

❤️ Usamos a extensão .ts e .tsx para componentes React

❤️ Também é possível usar com outros compiladores que suportam a linguagem como Babel

❤️ Temos todas as funcionalidades do javascript acrescidas dos recursos do typescript

❤️ Não precisamos ficar adivinhando o tipo das coisas e o vscode nos ajuda nisso. Podemos massar o mouser por cima que ele poderá dar os tipos. Assim, podemos copiar e colar para as nossas interfaces

image

❤️ Podemos adicionar o comentário //@ts-check em um arquivo ts para vermos os avisos do typescript.

❤️ O ts não pode ser compilado diretamente pelo browser, precisamos de um compilador (ex: babel) para transformar em js

❤️ O comando tsc --init vai gerar o arquivo tsconfig.json com as configurações do typescript.

target: define qual versão do javascript o código será compilado

ES3: versão bem antiga do javascript

ESNext: versão mais recente

strict: define várias configurações em cadeira. Ex: os dados devem ter uma tipagem explicita

Comando ts -w compila com watch

Annotation: é o ato de descrever qual tipagem um objeto, variável, etc, tem

Inference ("implicity"): é o ato de inferir (deduzir) qual é tipo das coisas. É uma boa prática não declarar o tipo quando o ts não solicita pois já inferiu, seria redundante.

runtime: em execução


Declarando variáveis

Ao declarar uma variável, precisamos deixar explicito o tipo dela (number, string, boolean, etc)

Any

Dentro desses tipos de variáveis também podemos encontrar o any, que é um tipo que pode ser modificado para qualquer outro tipo presente na linguagem, seja string, number ou qualquer outra coisa.

Sem adicionar nenhuma indicação de tipo, as variáveis no typescript são do tipo any, o que significa que elas podem conter qualquer tipo de dados, assim como o js.

Arrays

Arrays são um caso comum de tipos genéricos.

Never

Se uma função for jogada (throw), ela terá um tipo never.

Unknown

O unknown é um tipo de contrapartida segura do any, garantindo que alguma verificação de tipo seja executada antes que o valor possa ser usado. É melhor usado quando voce não sabe o tipo do dado a ser tipado. Para adicionar um tipo depois, voce vai precisar usar o cast.

Void

Funções que não retornam nada, apenas executam

Copiando tipos

O typeof permite com que façamos uma "cópia" da declaração de um tipo de uma variável para outra. Podemos usar uma interface para ter mais ou menos esse mesmo efeito, mas de forma nomeada. Por exemplo:

interface Point {
  x: number;
  y: number;
}
 
let point: Point;
let point2: Point;

Essa alteração permite que o tipo Point seja usado em vários locais dentro do código sem precisar redefinir os detalhes do tipo repetias vezes.

Sobrecarga de funções

A ordem da declaração dessas funções importa para o que o typescript possa escolher sobre qual o value mais se corresponde ao tipo declarado em cada uma delas.

function numberStringSwap(value: number, radix?: number): string;
function numberStringSwap(value: string): number;
function numberStringSwap(value: any, radix: number = 10): any {
    if (typeof value === 'string') {
        return parseInt(value, radix);
    }
    else if (typeof value === 'number') {
        return String(value);
    }
}

Definição de tipos

  1. number
  2. array
  3. string
  4. boolean
  5. any
  6. unknown
  7. tuple
  8. enum
  9. null
  10. undefined
  11. void

Casting

Casting é o processo de sobrescrever um tipo usando as chaves as ou <>. Exemplo:

let x: unknown = 'hello'; // Aqui a variável x é do tipo desconhecida
console.log((<string>x).length); // Mas aqui estamos usando o casting (as) para dizer que agora é do tipo string, sobrescrevendo seu tipo.

Vale lembrar, que o casting só vai funcionar se a variável tiver um tipo anterior. Ou seja, se usarmos o valor diretamente no lugar na variável vamos ter um erro.

A chave readonly pode prevenir arrays de serem mudados

const car: {type: string, mileage?: number } = {
  type: "Toyota"
}

Enum representa um grupo de constantes

É possível misturar e dar match em enum values de string e numeros, mas não é recomendável.

// the : number here specifies that this function returns a number
function getTime(): number {
  return new Date().getTime();
}

Por padrão, o typescript vai assumir que todos os parametros são obrigatórios, mas eles podem ser marcados como opcionais.

/* O operador ? vai fazer o parametro c ser opcional */
function add(a: number, b: number, c?: number) {
  return a + b + (c || 0); 
}

Default Params

Exemplo sobre como definir um valor padrão para um parametro. O typescript pode atribuir o tipo de acordo com o valor passado.

function pow(value: number, exponent: number = 10) {
  return value ** exponent;
}

Desestruturação com tipagem

// Desestruturação de parametros na função 
function divide({ dividend, divisor }: { dividend: number, divisor: number }) { ... }

Rest Params

Parametros Rest podem ser enviados, mas o tipo deve ser sempre um array.

// rest é um array de números. [] indica que é um array 
function add(a: number, b: number, ...rest: number[] {
  return a + b + rest.reduce((p, c) => p + c, 0)
}
  • Quando voce está escrevendo um código typescript que precisa acessar as declarações de ambiente, um comentário de referencia especial deve ser adicionado ao tipo do módulo que precisa dele.

Utility Types

interface Point {
  x: number;
  y: number;
}

let pointPart: Partial<Point> = {};

O fato de não declararmos o tipo da variável explicitamente não significa que ela não possui um tipo, mas este será dado pelo compilador de acordo com o valor que ela possui

Optional Chaining (?.)

Optional Chaining é uma feature do js que trabalha bem lidando com valores nulos. Ele permite acessar propriedades em um objeto, que podem ou não existir de forma compacta. Exemplo: house.yard?.sqft

Nullish Coalescence (??)

Nullish Coalescence é outra feature do js que também trabalha bem lidando com o null do typescript. Ele permite escrever expressões que tem um fallback especifico quando lida com o null ou undefined. Isso é util quando valores falsos ocorrerem na expressão mas ainda for válido.

Passando o tipo como parametro

function createPair<S, T>(v1: S, v2: T): [S, T] {
  return [v1, v2]
}

console.log(createPair<string, number>('hello', 42)); // ['hello', 42]

React com Typescript

É bem comum que os componentes recebam a props children, que recebemos dessa forma:

import { ReactNode } from 'react';

type Props = {
  children: ReactNode;
};

function Component({ children }: Props) {
  return (
    <div>
      {children}
    </div>
  );
}

export default Component;

Porém, podemos escrever de uma forma mais simplificada com PropsWithChildren e ter o mesmo efeito, porém com o children opcional e possivelmente undefined:

import { PropsWithChildren } from 'react';

function Component({ children }: PropsWithChildren) {
  return (
    <div>
      {children}
    </div>
  );
}

export default Component;

Existem casos onde temos um componente de design, como um input, em que temos que passar várias propriedades referentes a ele. Podemos fazer isso de uma forma explicita:

import React from 'react'

type Props = {
  label: string;
  className: string;
  onChange: () => void;
}

export default function Input({ label, className, onChange }: Props) {
  return (
    <div style={{ marginBottom: '1rem' }}>
      <label htmlFor={label}>{label}</label>
      <input className={className} onChange={onChange} type="text" id={label} name={label}></input>
    </div>
  )
}

Porém, podemos fazer isso de uma forma implicita e permitir que qualquer propriedade que seja atralada ao input por padrão possa ser passado ao nosso componente, sem a necessidade de criar novas props a todo momento usando o ComponentProps

import React from 'react'

type Props = React.ComponentProps<'input'> & {
  label: string
}

export default function Input({ label, ...rest }: Props) {
  return (
    <div style={{ marginBottom: '1rem' }}>
      <label htmlFor={label}>{label}</label>
      <input type="text" id={label} name={label} {...rest}></input>
    </div>
  )
}

Componente Checkbox simples

import React, { useState } from 'react'

export default function Checkbox({ label }: { label: string }) {
  const [checked, setChecked] = useState(false);

  // Se deixarmos essa função anonima o typescript vai inferir
  function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
    setChecked(event.currentTarget.checked);
  }

  return (
    <label>
      <input type="checkbox" checked={checked} onChange={handleChange}/>
      {label}
    </label>
  )
}

Construindo um hook para fetch bem simples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment