Languages
TypeScript
Functions

Functions

Call signature

A sintaxe da expressão do tipo de função não permite a declaração de propriedades. Se quisermos descrever algo que pode ser chamado com propriedades, podemos escrever uma assinatura de chamada em um tipo de objeto:

type DescribableFunction = {
    description: string;
    (someArg: number): boolean;
};
 
function doSomething(fn: DescribableFunction) {
    console.log(fn.description + " returned " + fn(6));
}
 
const myFunc: DescribableFunction = (someArg: number) => {
    return someArg > 0;
  };
 
myFunc.description = "myFunc";
 
doSomething(myFunc);

Generic Functions

No TypeScript, os genéricos são usados ​​quando queremos descrever uma correspondência entre dois valores.

function firstElement<T>(arr: T[]): T | undefined {
    return arr[0];
}
 
const first = firstElement<number>([1, 2, 3]);
const firstString = firstElement<string>(["a", "b", "c"]);

Inference

O TypeScript pode inferir o tipo de parâmetro de tipo de uma função se o tipo de retorno for especificado.

function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {
  return arr.map(func);
}
 
// Parameter 'n' is of type 'string'
// 'parsed' is of type 'number[]'
const parsed = map(["1", "2", "3"], (n) => parseInt(n));

Constraints

Podemos usar restrições para restringir o tipo de parâmetro de tipo de uma função.

function longest<Type extends { length: number }>(a: Type, b: Type) {
  if (a.length >= b.length) {
    return a;
  } else {
    return b;
  }
}
 
const longerArray = longest([1, 2], [1, 2, 3]);
const longerString = longest("alice", "bob");
const notOK = longest(10, 100); // Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.

Optional Parameters

Os parâmetros opcionais são parâmetros que não são obrigatórios. Podemos usar o operador de atribuição de parâmetro opcional (?) para marcar um parâmetro como opcional.

function buildName(firstName: string, lastName?: string) {
  if (lastName) return firstName + " " + lastName;
  else return firstName;
}
 
buildName("Bob"); // works correctly now

Function Overloads

Podemos usar sobrecarga de função para criar uma função que pode ser chamada de várias maneiras. Cada sobrecarga terá uma assinatura de função diferente. A assinatura de implementação também deve ser compatível com as assinaturas de sobrecarga.

  • A assinatura da implementação não é visível do lado de fora. Ao escrever uma função sobrecarregada, você sempre deve ter duas ou mais assinaturas acima da implementação da função.
  • Sempre prefira parâmetros com tipos de união em vez de sobrecargas quando possível
// Overloads signatures
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
 
// Implementation signature
function makeDate(timestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, timestamp, d);
  } else {
    return new Date(timestamp);
  }
}
 
const d1 = makeDate(12345678);
const d2 = makeDate(5, 5, 5);
const d3 = makeDate(new Date().getDate());

Void

void representa o valor de retorno de funções que não retornam um valor. É o tipo inferido sempre que uma função não possui nenhuma instrução de retorno ou não retorna nenhum valor explícito dessas instruções de retorno:

function warnUser(): void {
  console.log("This is my warning message");
}

Object

O tipo object representa um valor não-primitivo. Como não há nenhum tipo que inclua todos os tipos de objeto, você pode precisar usar o tipo object em casos em que você não sabe exatamente qual tipo de objeto você está lidando.

declare function create(o: object | null): void;
 
create({ prop: 0 }); // OK
create(null); // OK

Unknown

O tipo unknown é um tipo de segurança que permite que você receba qualquer valor, mas força você a verificar e declarar o tipo antes de poder usá-lo. Isso é útil se você tiver uma API que retorna um valor de tipo desconhecido e você precisar garantir que você trate esse valor de maneira segura antes de usá-lo.

function f1(a: any) {
  a.b(); // OK
}
 
function f2(a: unknown) {
  a.b(); // Object is of type 'unknown'.
}

Never

O tipo never representa o tipo de valores que nunca ocorrem. Por exemplo, never é o tipo de retorno para uma função que sempre lança uma exceção ou uma função que nunca retorna; Variáveis ​​do tipo never só podem ser never; Nenhum valor pode ser atribuído a uma variável do tipo never.

function error(message: string): never {
  throw new Error(message);
}
 
function fail() {
  return error("Something failed");
}
 
function infiniteLoop(): never {
  while (true) {}
}

Rest Parameters and Arguments

Os parâmetros rest permitem representar um número indefinido de argumentos como um array. Os parâmetros rest devem ser os últimos parâmetros de uma função.

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}
 
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

O TypeScript não assume que os arrays são imutáveis. Isso pode levar a alguns comportamentos surpreendentes:

const args = [8, 5];
const angle = Math.atan2(...args); // Um argumento spread deve ter um tipo de tupla ou ser passado para um parâmetro rest
 
// Infer as tuple type [number, number]
const args = [8, 5] as const;

Spread Operator

O operador de propagação permite que um array seja expandido em lugares onde zero ou mais argumentos (para chamadas de função) ou elementos (para literais de array) são esperados ou um objeto seja expandido em lugares onde zero ou mais pares de chave-valor (para literais de objeto) são esperados.

let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5];

Assignability of Functions

A digitação contextual com um tipo de retorno void não força as funções a não retornarem algo. Outra maneira de dizer isso é um tipo de função contextual com um tipo de retorno void (tipo vf = () => void), quando implementado, pode retornar qualquer outro valor, mas será ignorado.

type voidFunc = () => void;
 
const f1: voidFunc = () => {
  return true;
};
 
const f2: voidFunc = () => true;
 
const f3: voidFunc = function () {
  return true;
};