Aguarde...

24 de julho de 2021

Funções em TypeScript: uma introdução simples

Funções em TypeScript: uma introdução simples

As funções são parte fundamental do JavaScript. Eles ajudam a tornar o código reutilizável, mantendo-o flexível. O TypeScript leva esses benefícios adiante, ajudando você a escrever funções de segurança de tipos. Este tutorial mostrará como usar funções no TypeScript, como especificar tipos para parâmetros, tipos de retorno e muito mais.

Nada de novo, apenas mais seguro?

As funções estão entre os recursos de linguagem usados ​​com mais frequência. Isso se aplica não apenas a JavaScript e TypeScript, mas também a outras linguagens de programação. No entanto, em JavaScript, há um problema. JavaScript não é uma linguagem de programação de tipo estático. Por causa disso, existem algumas coisas que você não pode fazer.

Por exemplo, ao definir uma função, você não pode especificar os tipos permitidos para seus parâmetros. Isso torna mais fácil chamar uma função com argumento de um tipo errado. Você pode criar uma função que recebe dois números como parâmetros e chamá-la passando duas strings como argumentos. JavaScript não vai te impedir.

Você também não pode especificar o tipo de retorno de uma função. Isso pode levar a problemas quando uma parte do programa que chama uma função espera obter algo enquanto a função retorna algo diferente. É aqui que o TypeScript pode ser útil. É verdade que o TypeScript não adiciona nada de novo às funções.

As funções no TypeScript ainda são funções, aquelas funções que você conhece do JavaScript. O que o TypeScript faz é tornar as funções mais seguras e previsíveis. Ele faz isso combinando funções com seu poderoso sistema de tipos. Isso ajuda a garantir que suas funções recebam e retornem os tipos corretos. Vamos dar uma olhada em como.

Tipos de parâmetros

Ao criar uma função, você também pode especificar quaisquer parâmetros que ela aceite. Isso torna seu código mais flexível e fácil de reutilizar em diferentes condições. Com o TypeScript, você também pode especificar tipos para esses parâmetros. Quando você tenta chamar qualquer função com um argumento de um tipo errado, o TypeScript irá avisá-lo.

A sintaxe para definir tipos de parâmetros de função é simples. É composto por dois pontos ( :) e o tipo. Primeiro, você define um parâmetro. Em seguida, você adiciona dois pontos logo após. Depois disso, você especifica que tipo é permitido para aquele parâmetro específico.

// Create a function that accepts two parameters: str1 and str2.
// Both parameters must be of type string.
function joinStrings(str1: string, str2: string) {
  return str1 + str2
}

// This will work:
joinStrings('Wo', 'rld')
// Output:
// 'World'

// This will not work:
joinStrings('Hel', 135)
// TS error: Argument of type 'number' is not assignable to parameter of type 'string'.

O TypeScript também permite que você especifique vários tipos. Você pode conseguir isso usando tipos de união . Isso basicamente significa que você pode pegar dois ou mais tipos e informar ao TypeScript que qualquer um desses tipos pode ser usado. Quando você deseja usar tipos de união, você especifica todos os tipos possíveis e usa |para separá-los.

// Create a function that accepts one parameter.
// This parameter can be either number, string or boolean.
function numStrBool(val: number | string | boolean) {
  return typeof val
}

// This will work in TypeScript:
numStrBool(15)
// Output:
// 'number'

// This will also work in TypeScript:
numStrBool('Tea')
// Output:
// 'string'

// This will also work in TypeScript:
numStrBool(true)
// Output:
// 'boolean'

// This will not work in TypeScript:
numStrBool({ key: 15 })
// TS error: Argument of type '{ key: number; }' is not assignable to parameter of type 'string | number | boolean'.

Parâmetros opcionais

Assim como no JavaScript, você também pode marcar alguns parâmetros como opcionais no TypeScript. A sintaxe é a mesma. Para marcar um parâmetro como opcional, você adiciona um ponto de interrogação ( ?) logo depois dele. Quando você trabalha com funções no TypeScript, o ponto de interrogação vai depois do nome do parâmetro e antes dos dois pontos e do tipo.

// Create a function that accepts two parameters,
// the first one required and the second optional:
function combineWords(word1: string, word2?: string) {
  return `${word1}${word2 ? word2 : ''}`
}

// This will work in TypeScript:
combineWords('Hello', 'world')
// Output:
// 'Helloworld'

// This will also work in TypeScript:
combineWords('Say', 'Bye')
// Output:
// 'SayBye'

// This will also work in TypeScript:
combineWords('Hi')
// Output:
// 'Hi'

// This will not work in TypeScript:
combineWords()
// TS error: Expected 1-2 arguments, but got 0.

Parâmetros padrão

O TypeScript também permite definir valores padrão para os parâmetros da função. Isso não é tudo. Ao definir valores padrão para funções no TypeScript, você não precisa especificar tipos para esses parâmetros explicitamente. O TypeScript poderá usar valores padrão para inferir tipos de parâmetros automaticamente. Menos trabalho para você.

A sintaxe dos valores padrão é a mesma do JavaScript . Você especifica um parâmetro e logo depois adiciona um sinal de igual com o valor padrão. Se você também deseja especificar explicitamente um tipo para o parâmetro, especifique o tipo primeiro. Isso significa usar a seguinte ordem: nome do parâmetro, dois pontos e tipo, sinal de igual e valor padrão.

// Example 1: default parameters and implicit type:
// Create a function that accepts two parameters.
// Both parameters are of type numbers,
// the second has default value 0.
function addTwoNumbers(num1: number, num2 = 0) {
  return num1 + num2
}
// TS will add type for num2 implicitly:
// addTwoNumbers(num1: number, num2: number = 0)

// This will work in TypeScript:
addTwoNumbers(98, 656)
// Output:
// 754

// This will also work in TypeScript:
addTwoNumbers(63)
// Output:
// 63

// This will not work in TypeScript:
addTwoNumbers('13')
// TS error: Argument of type 'string' is not assignable to parameter of type 'number'.


// Example 2: default parameters and explicit type:
function addTwoNumbers(num1: number, num2: number = 0) {
  return num1 + num2
}

Parâmetros de descanso

Algumas funções podem aceitar um número arbitrário de argumentos. É aqui que a sintaxe dos parâmetros restantes será muito útil. No TypeScript, você pode especificar o tipo para os parâmetros restantes tão facilmente quanto qualquer outro parâmetro. A sintaxe é a mesma. Você adiciona o parâmetro resto e segue com dois pontos e o tipo.

Ao trabalhar com parâmetros de repouso, lembre-se de uma coisa. Os parâmetros passados ​​como parâmetros restantes serão coletados em uma matriz. Isso significa que você também deve usar o tipo de array, type[]ou Array<type>.

// Create a function that accepts two parameters.
// The first parameter is a string.
// The second is a rest parameter and is an array of strings.
function buildATeam(leader: string, ...teammates: string[]) {
  return `Team is composed of ${leader} as a the team leader and ${teammates.length > 0 ? teammates.join(', ') : 'nobody'} as the core team.`
}

// This will work in TypeScript:
buildATeam('Joe', 'Vicky', 'Thomas')
// Output:
// 'Team is composed of Joe as a the team leader and Vicky, Thomas as the core team.'

// This will also work in TypeScript:
buildATeam('Sandra', 'Alex', 'Jack', 'Victor')
// Output:
// 'Team is composed of Sandra as a the team leader and Alex, Jack, Victor as the core team.'

// This will also work in TypeScript:
buildATeam('Stuart')
// Output:
// 'Team is composed of Stuart as a the team leader and nobody as the core team.'

// This will not work in TypeScript:
buildATeam(13, 15)
// TS error: Argument of type 'number' is not assignable to parameter of type 'string'.

Tipos de retorno

O TypeScript também permite que você especifique o tipo de retorno de uma função. Dito isso, você não fará isso com muita frequência. Na maioria dos casos, o TypeScript será capaz de inferir o tipo de retorno da função com base nas instruções de retorno dentro da própria função. Você não precisa especificar esses tipos explicitamente.

E se o TypeScript não for capaz de inferir o tipo de retorno ou você quiser especificá-lo sozinho? Para especificar o tipo de retorno da função, você deve adicionar dois pontos e o tipo logo após a lista de parâmetros, antes do corpo da função.

// Create a function that accepts two parameters.
// Both parameters are numbers.
// Set the return type to be a number (the '): number {' part).
function numToPow(num: number, exp: number): number {
  return num ** exp
}

// This will work in TypeScript:
numToPow(15, 8)
// Output:
// 2562890625

// This will not work in TypeScript:
numToPow(12, '9')
// TS error: Argument of type 'string' is not assignable to parameter of type 'number'.

Tipos de função

Quando você trabalha com funções no TypeScript, geralmente define todos os seus tipos ao declarar uma função. O que o TypeScript também permite é definir uma assinatura de função antes de você realmente criar a própria função. Posteriormente, quando você criar a função, o TypeScript usará a assinatura para inferir todos os tipos para você automaticamente.

Essa assinatura é chamada de tipo de função. Pode ser útil quando você espera uma assinatura de função específica. Este tipo de função é composto por duas partes: parâmetros e tipo de retorno. Ao declarar um tipo de função, você deve especificar ambas as partes.

// Create function type for function subtract.
// This function accepts two parameters, both are numbers.
// Its return type is also a number.
let subtract: (a: number, b: number) => number

// Assign the actual function to the variable:
subtract = function (a, b) {
  return a - b
}

// This will not work in TypeScript:
subtract = function (a: string, b: string) {
  return a + b
}
// TS error: Type '(a: string, b: string) => string' is not assignable to type '(a: number, b: number) => number'.

Lembre-se de que, ao declarar o tipo de função, não é necessário especificar os tipos novamente ao atribuir a função real. O TypeScript inferirá todos os tipos implicitamente com base no tipo de função que você criou anteriormente.

// Create function type for function subtract:
let subtract: (a: number, b: number) => number

// These types are redundant:
subtract = function (a: number, b: number) {
  return a - b
}

Existe outra maneira de conseguir isso. Você também pode criar um tipo de função durante a atribuição de função. Isso permite que você combine as duas etapas em uma.

// Create function with function:
let subtract: (a: number, b: number) => number = function (a: number, b: number) {
  return a - b
}

Tipos de função com tipos e interfaces

Essas maneiras de criar o tipo de função que acabamos de discutir têm uma desvantagem. Eles não são realmente reutilizáveis. Você cria um tipo de função, atribui a ele uma função e pronto. Você não pode usar esse tipo novamente para outra função, a menos que copie o código. Felizmente, existe outra maneira, na verdade duas.

Você também pode criar tipos de função com tipos e interfaces . O benefício de ambos é a já mencionada reutilização. O tipo e a interface não deixarão de existir depois de usá-los. Ao criar um tipo de função com um tipo ou interface, você pode usá-lo sempre que quiser e quantas vezes quiser.

A sintaxe de tipo para declarar um tipo de função é muito semelhante à sintaxe que você viu acima. Existem apenas duas diferenças. Primeiro, você substituirá a palavra-chave variável por palavra- typechave. Em segundo lugar, você substituirá os dois pontos após o nome da variável pelo sinal de igual. Basicamente, você está criando um novo tipo e atribuindo a ele uma assinatura de função.

Quando quiser usar seu novo tipo, use-o junto com dois pontos, ao criar uma nova expressão de função .

// Function type with variable:
let subtract: (a: number, b: number) => number

// Function type with type:
type TakeNumsReturnNums = (a: number, b: number) => number

// Use the "TakeNumsReturnNums" type with function expression:
const subtract: TakeNumsReturnNums = (a, b) => a - b

// This will work in TypeScript:
subtract(97, 13)
// Output:
// 84

// This will not work in TypeScript:
subtract(55, '15')
// TS error: Argument of type 'string' is not assignable to parameter of type 'number'.


// Use the type again:
const sumNumbers: TakeNumsReturnNums = (x, y) => x + y

// And again:
const divideNumbers: TakeNumsReturnNums = (c, d) => c / d

Fazer o mesmo com uma interface requer uma sintaxe diferente. Você cria uma nova interface. Dentro dele, você especificará os tipos de lista de parâmetros como a chave e o tipo de retorno como o valor. Então, você o usa da mesma maneira que o tipo.

// Create interface for subtract function:
interface TakeNumsReturnNums {
  // Syntax:
  // (types for parameter list): return type;
  (a: number, b: number): number;
}

// Use the "TakeNumsReturnNums" interface with function expression:
const subtract: TakeNumsReturnNums = (a, b) => a - b

// This will work in TypeScript:
subtract(55, 21)
// Output:
// 34

// This will not work in TypeScript:
subtract(true, 66)
// TS error: Argument of type 'boolean' is not assignable to parameter of type 'number'.

// Use the type again:
const sumNumbers: TakeNumsReturnNums = (x, y) => x + y

// And again:
const divideNumbers: TakeNumsReturnNums = (c, d) => c / d

Conclusão: Funções em TypeScript

O TypeScript facilita a escrita de funções com segurança de tipos e mais previsíveis. Espero que este tutorial tenha ajudado você a entender como usar funções no TypeScript. Como definir tipos para parâmetros e tipos de retorno e como criar tipos de função.

Postado em Blog
Escreva um comentário