No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Sobrecarga de funciones: el problema

10/22
Recursos

Con la sobrecarga de funciones definimos diferentes firmas de una funci贸n en la que cada firma puede manejar cierto tipado de entrada y salida. TypeScript decidir谩 de manera autom谩tica qu茅 firma es la correcta para usar bas谩ndose en los argumentos enviados y el tipo de datos de estos.

Un problema que puede resolver la sobrecarga de funciones

Imaginemos que deseamos implementar una funci贸n que devuelva un string en el caso de que le env铆es un array o que devuelva un array en caso de que le mandes un string como argumento:

// 1锔忊儯Si le enviamos un array, nos debe unir cada elemento del array y devolver un string.
// 2锔忊儯Si le enviamos un string, nos debe separar cada caracter y formar un array como respuesta.
// [N,i,c,o] => 'Nico' ... string[] => string 1锔忊儯
// 聽'Nico' => [N,i,c,o] ... string => string[] 2锔忊儯


function parseStr(input: string | string[]): string | string[] {
聽 if (Array.isArray(input)) {
聽 聽 return input.join(''); // string
聽 } else {
聽 聽 return input.split(''); // string[]
聽 }
}

// Llamando a la funci贸n...
const rptaArray = parseStr('Nico'); // Entrada: string - Salida: Array
console.log('rptaArray', 'Nico =>' ,rptaArray);

const rptaStr = parseStr(['N','i','c','o']); // Entrada: array - Salida: string
console.log('rptaStr', "['N','i','c','o'] =>",rptaStr); 

Definimos la funci贸n con un par谩metro que puede ser del tipo string o string[] (un array que contiene valores de tipo string) y un retorno que puede ser de igual manera string o string[].

Cuando invocamos la funci贸n para enviar los argumentos que deseamos probar, TypeScript no sabe inicialmente qu茅 tipo de dato le est谩s mandando de manera espec铆fica en el c贸digo. Por tanto, no podemos acceder en la siguiente l铆nea de c贸digo a ning煤n m茅todo propio de un string o un array:

const rptaArray = parseStr('Nico'); // Entrada: string - Salida: Array
// La salida y por tanto el valor que es asignado a `rptaArray` ser谩 un Array.
// Si intentamos aplicar un m茅todo propio de los Arrays:
rptaArray.reverse(); // 鉀 ...Nos marcar谩 error 馃憖

const rptaStr = parseStr(['N','i','c','o']); // Entrada: array - Salida: string
// La salida y por tanto el valor que es asignado a `rptaStr` ser谩 un string.
// Si intentamos aplicar un m茅todo propio de los strings:
rptaStr.toLowerCase(); // 鉀 ...Nos marcar谩 error 馃憖

Soluci贸n con validaci贸n de tipos

Una posible soluci贸n es realizar una peque帽a validaci贸n de tipos previo a querer ejecutar alg煤n m茅todo propio del tipo de dato correspondiente:

const rptaArray = parseStr('Nico');
// rtaArray.reverse(); 鉀 NO directamente
if (Array.isArray(rtaArray)) { //鉁 Validaci贸n de tipos previamente...
聽 rtaArray.reverse(); // 馃憤 Ahora s铆 nos permite utilizar este m茅todo de los arrays.
}
console.log('rtaArray', 'Nico =>' ,rtaArray); // Vemos en consola


const rtaStr = parseStr(['N','i','c','o']);
// rtaStr.toLowerCase(); 鉀 NO directamente
if (typeof rtaStr === 'string') { //鉁 Validaci贸n de tipos previamente...
聽 rtaStr.toLowerCase(); // 馃憤 Ahora s铆 nos permite utilizar este m茅todo de los strings.
}
console.log('rtaStr', "['N','i','c','o'] =>",rtaStr); // Vemos en consola

Soluci贸n con sobrecarga de funciones

Para resolver este problema con sobrecarga de funciones debemos declarar 2 firmas adicionales con el mismo nombre de la funci贸n: una firma manejar谩 el tipado de entrada/salida como string/string[] y la otra forma de manera viceversa, es decir string[]/string. El par谩metro de la funci贸n que tendr谩 la l贸gica puede manejar el tipado unknown, pues ya estamos dejando declarado previamente los tipados de entrada y salida que manejar谩 la funci贸n:

// SOBRECARGAS:
function parseStr(input: string): string[]; // Entrada: string - Salida: string[]
function parseStr(input: string[]): string; // Entrada: string[] - Salida: string

// Funci贸n principal con las instrucciones deseadas y a la que se le aplicar谩n las sobrecargas:
function parseStr(input: unknown): unknown {
}

Ahora en la funci贸n principal haremos una validaci贸n de tipos y seg煤n ello retornaremos las respuestas respectivas a lo que se busca como output:

// SOBRECARGAS:
function parseStr(input: string): string[]; // Entrada: string - Salida: string[]
function parseStr(input: string[]): string; // Entrada: string[] - Salida: string

// Funci贸n principal y a la que se le aplicar谩n las sobrecargas:
function parseStr(input: unknown): unknown {
聽 聽 if (Array.isArray(input)) {
聽 聽 聽 聽 return input.join(''); // string
聽 聽 } else {
聽 聽 聽 聽 return input.split(''); // string[]
聽 聽 }
}

Finalmente, ya podr铆amos utilizar los m茅todos seg煤n el tipo de dato de la respuesta obtenida de la funci贸n:

// SOBRECARGAS:
function parseStr(input: string): string[]; // Entrada: string - Salida: string[]
function parseStr(input: string[]): string; // Entrada: string[] - Salida: string

// Funci贸n principal y a la que se le aplicar谩n las sobrecargas:
function parseStr(input: unknown): unknown {
聽 聽 if (Array.isArray(input)) {
聽 聽 聽 聽 return input.join(''); // string
聽 聽 } else {
聽 聽 聽 聽 return input.split(''); // string[]
聽 聽 }
}

const rtaArray = parseStr('Nico'); // Salida: array
rtaArray.reverse(); // 鉁 Ya podemos acceder a los m茅todos de un array 
console.log('rtaArray', 'Nico =>' ,rtaArray);

const rtaStr = parseStr(['N','i','c','o']); // Salida: string
rtaStr.toLowerCase(); // 鉁 Ya podemos acceder a los m茅todos de un string 
console.log('rtaStr', "['N','i','c','o'] =>",rtaStr);

Contribuci贸n creada por: Mart铆n 脕lvarez (Platzi Contributor).

Aportes 8

Preguntas 0

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

La manera en como yo lo hago normalmente es con el operador as para indicarle a TS el tipo de dato que quiero en ciertos casos.

const resArr = parseStr("Marisol") as string[];

En el caso de arriba yo le estoy mandando un string, por lo que se que recibir茅 un array como respuesta.

Les comparto mis apuntes. 馃槃

Problema con el retorno de funciones

Cuando tenemos una funci贸n que retorna m谩s de un solo tipo de dato y a ese resultado lo queremos utilizar en otra parte de nuestro programa, no vamos a poder usarlo como tal, ya que TypeScript no sabe que tipo de dato se retorn贸 realmente.

TypeScript al no saber el tipo de dato que se retorn贸 en una funci贸n que puede retornar m谩s de un tipo de dato, somos nosotros los responsables en decirle el tipo de dato resultante de la funci贸n para as铆 poder operar con el resultado de forma normal.

Uso de la sobrecarga de funciones

Se suele emplear mucho en librer铆as, pero depende mucho de tu proyecto y de las ventajas que te puede llegar a dar.

La sobre carga de funciones 煤nicamente suelen darse con las funciones declarativas con la palabra reservada function.

const p =(i: any,...any: any)=>console.log(`\n\t(${i})=>`,...any);

/**
 * Virus => [V,i,r,u,s] => string => string[]
 * [V,i,r,u,s] => Virus => string[] => string
 */

function parseStr(
 input: string | string[]
): string | string[] {

	if(Array.isArray(input)){
		return input.join("")
	}else{
		return input.split("")
	}
}

const rta0 = parseStr(["V","i","r","u","s"])
	p(0, rta0)

const rta1 = parseStr("Virus")
	p(1, rta1)

function parseWord (input: string | string[]): string | string[] {
  return (Array.isArray(input)) ? input.join('') : [...input];
}

const first = parseWord('EDGAR') as string[];
const second = parseWord(first) as string;
const third = parseWord(second);

console.log(first);
console.log(second);
console.log(third);
frase divertida "typescript no puede inferir la l贸gica"
  • funciones declarativas usan palabra reservada
    function.

  • funciones de expresion son las que usan el const como las arrow functions.

Prob茅 con realizar la Sobrecarga de funciones en la sintaxis con const y arrow functions y me funcion贸, no s茅 si haya alguna consecuencia que no haya podido percibir:

const parseString = (input:string| string[]): string | string[] => {
  if(Array.isArray(input)){
    return input.join('');
  } else {
    return input.split('');
  }
}

otra forma de preguntar seria as铆

typeof res === "string" ? res.toLocaleLowerCase() : res.reverse();