TechLead
Lección 4 de 8
5 min de lectura
TypeScript

Funciones en TypeScript

Tipa parámetros y valores de retorno, sobrecargas y expresiones de tipo de función

Anotaciones de tipo en funciones

// Función básica con tipos
function add(a: number, b: number): number {
  return a + b;
}

// Función flecha con tipos
const multiply = (a: number, b: number): number => {
  return a * b;
};

// Inferencia del tipo de retorno
function subtract(a: number, b: number) {
  return a - b;  // tipo de retorno inferido como number
}

// Tipo de retorno void
function logMessage(message: string): void {
  console.log(message);
}

// Tipo de retorno never (lanza error o bucle infinito)
function fail(message: string): never {
  throw new Error(message);
}

Parámetros opcionales y por defecto

// Parámetro opcional (debe ir después de los requeridos)
function greet(name: string, greeting?: string): string {
  return `${greeting || "Hello"}, ${name}!`;
}

greet("Alice");           // "Hello, Alice!"
greet("Bob", "Hi");       // "Hi, Bob!"

// Parámetro por defecto
function greetWithDefault(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}!`;
}

greetWithDefault("Alice");        // "Hello, Alice!"
greetWithDefault("Bob", "Hi");    // "Hi, Bob!"

// Por defecto con inferencia de tipo
function createUser(name: string, role = "user") {
  // role se infiere como string
  return { name, role };
}

Parámetros rest

// Parámetros rest
function sum(...numbers: number[]): number {
  return numbers.reduce((acc, num) => acc + num, 0);
}

sum(1, 2, 3);        // 6
sum(1, 2, 3, 4, 5);  // 15

// Rest con otros parámetros
function buildName(firstName: string, ...restOfName: string[]): string {
  return firstName + " " + restOfName.join(" ");
}

buildName("John", "Paul", "Jones");  // "John Paul Jones"

// Parámetros rest tipados con tuplas
function readButtonInput(...args: [string, number, ...boolean[]]): void {
  const [name, version, ...flags] = args;
  console.log(name, version, flags);
}

Expresiones de tipo de función

// Expresión de tipo de función
type MathOperation = (a: number, b: number) => number;

const add: MathOperation = (a, b) => a + b;
const subtract: MathOperation = (a, b) => a - b;

// Usar en otros tipos
interface Calculator {
  add: MathOperation;
  subtract: MathOperation;
  multiply: MathOperation;
  divide: MathOperation;
}

// Tipos para callbacks
type Callback = (error: Error | null, result?: string) => void;

function fetchData(url: string, callback: Callback): void {
  // ...
  callback(null, "data");
}

// Métodos de array con callbacks tipados
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((n: number): number => n * 2);

// Alias de tipo para manejador de eventos
type ClickHandler = (event: MouseEvent) => void;

Funciones genéricas

// Función genérica básica
function identity<T>(arg: T): T {
  return arg;
}

identity<string>("hello");  // tipo explícito
identity(42);               // inferido como number

// Genérico con restricciones
function getLength<T extends { length: number }>(arg: T): number {
  return arg.length;
}

getLength("hello");     // 5
getLength([1, 2, 3]);   // 3
// getLength(123);      // Error: number no tiene length

// Múltiples parámetros de tipo
function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

const result = pair("hello", 42);  // [string, number]

// Genérico con tipo por defecto
function createArray<T = string>(length: number, value: T): T[] {
  return Array(length).fill(value);
}

createArray(3, "x");   // string[] (explícito)
createArray(3, 42);    // number[] (inferido)
createArray<>(3, "x"); // string[] (por defecto)

Sobrecargas de funciones

// Sobrecargas de funciones
function makeDate(timestamp: number): Date;
function makeDate(year: number, month: number, day: number): Date;
function makeDate(yearOrTimestamp: number, month?: number, day?: number): Date {
  if (month !== undefined && day !== undefined) {
    return new Date(yearOrTimestamp, month - 1, day);
  }
  return new Date(yearOrTimestamp);
}

makeDate(1609459200000);     // Desde timestamp
makeDate(2024, 1, 15);       // Desde año, mes, día
// makeDate(2024, 1);        // Error: no hay sobrecarga válida

// Sobrecargas con distintos tipos de retorno
function getValue(key: "name"): string;
function getValue(key: "age"): number;
function getValue(key: "active"): boolean;
function getValue(key: string): string | number | boolean {
  const data: Record<string, string | number | boolean> = {
    name: "Alice",
    age: 30,
    active: true
  };
  return data[key];
}

const name = getValue("name");     // string
const age = getValue("age");       // number
const active = getValue("active"); // boolean

Parámetro this

// Tipo explícito de this
interface User {
  name: string;
  greet(this: User): string;
}

const user: User = {
  name: "Alice",
  greet() {
    return `Hello, I'm ${this.name}`;
  }
};

user.greet();  // "Hello, I'm Alice"

// const callback = user.greet;
// callback();  // Error: contexto 'this' de tipo 'void'

// this en métodos de clase
class Counter {
  count = 0;

  // La función flecha preserva 'this'
  increment = () => {
    this.count++;
  };

  // El método normal necesita binding
  decrement() {
    this.count--;
  }
}

Ejemplos prácticos

// Función de fetch para API
async function fetchUser(id: number): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

// Manejador de eventos
function handleClick(event: React.MouseEvent<HTMLButtonElement>): void {
  console.log("Clicked:", event.currentTarget);
}

// Utilidad debounce
function debounce<T extends (...args: any[]) => any>(
  func: T,
  wait: number
): (...args: Parameters<T>) => void {
  let timeoutId: ReturnType<typeof setTimeout>;

  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func(...args), wait);
  };
}

// Función de orden superior
function withLogging<T extends (...args: any[]) => any>(fn: T): T {
  return ((...args) => {
    console.log("Calling with:", args);
    const result = fn(...args);
    console.log("Result:", result);
    return result;
  }) as T;
}

Puntos clave

  • • Tipa parámetros y valores de retorno
  • • Usa ? para parámetros opcionales
  • • Usa parámetros rest con arrays tipados
  • • Las funciones genéricas permiten reutilización segura
  • • Las sobrecargas manejan múltiples firmas
  • • Sé explícito con this cuando sea necesario

Continuar Aprendiendo