TypeScript es un lenguaje de programación desarrollado y mantenido por Microsoft. Es un superset de JavaScript que agrega tipado estático opcional, y características orientadas a objetos. TypeScript permite a los desarrolladores escribir código más robusto y mantenible, mejorando la experiencia de desarrollo a través de herramientas de autocompletado, verificación de tipos en tiempo de compilación y soporte para programación modular.
Características principales de TypeScript
- Tipado Estático: TypeScript permite especificar tipos de datos (como
string
,number
,boolean
, etc.) para variables, parámetros y funciones. Esto ayuda a detectar errores en tiempo de compilación en lugar de en tiempo de ejecución, lo que puede hacer que el código sea más seguro y fácil de mantener. - Superset de JavaScript: Todo código JavaScript válido es también código TypeScript válido. Esto significa que puedes usar TypeScript en proyectos existentes de JavaScript sin necesidad de reescribir todo el código.
- Orientado a Objetos: TypeScript soporta características de Programación Orientada a Objetos (OOP), como clases, interfaces y herencia, lo que facilita la organización del código y su reutilización.
- Interoperabilidad: TypeScript se puede integrar fácilmente con bibliotecas y frameworks de JavaScript, como React, Angular y Vue.js.
- Compilación a JavaScript: TypeScript se compila a JavaScript puro, lo que significa que puedes ejecutar código TypeScript en cualquier entorno que soporte JavaScript, como navegadores web o servidores Node.js.
- Características Avanzadas: TypeScript incluye características como generics, enums, y tipos avanzados (uniones, intersecciones), lo que permite una mayor flexibilidad y expresividad en el código.
TypeScript es ampliamente utilizado en el desarrollo de aplicaciones web frontend y backend, especialmente en proyectos grandes y complejos donde la seguridad de tipos y la mantenibilidad del código son cruciales.
Variables y Constantes
Para declarar una variable o constante, se utiliza la palabra clave let
o const
seguida del nombre de la variable, un símbolo de dos puntos (:
) para especificar el tipo (opcional), y luego se asigna un valor con el símbolo de igual (=
)
let nombreVariable: tipo = valor;
const nombreConstante: tipo = valor;
Tipos de Datos
Tipos Inferidos
Se puede omitir el tipo de dato, de esta manera TypeScript va a inferir el tipo a partir del valor asignado:
let edad = 30; // TypeScript infiere que es un number
const saludo = "Hola"; // TypeScript infiere que es un string
Tipos Primitivos
Tipo de Dato | Descripción | Ejemplo |
---|---|---|
number |
Representa tanto enteros como números de punto flotante. | let edad: number = 30; |
string |
Representa texto. | let nombre: string = "Carlos"; |
boolean |
Representa un valor verdadero o falso. | let esDesarrollador: boolean = true; |
null |
Representa la ausencia intencionada de un valor. | let valorNulo: null = null; |
undefined |
Indica que una variable no ha sido inicializada. | let valorIncierto: undefined; |
Ejemplo:
const name: string = "Carlos";
let age: number = 30;
let isActive: boolean = true;
Tipos de Estructura
Tipo de Dato | Descripción | Ejemplo |
---|---|---|
array |
Colección de valores del mismo tipo. | let numeros: number[] = [1, 2, 3]; |
array |
Colección de valores del mismo tipo. | let nombres: Array<string> = ["Carlos", "Ana", "Luis"]; |
tuple |
Array con un número fijo de elementos de diferentes tipos. | let persona: [string, number] = ["Carlos", 30]; |
Arrays
TypeScript permite dos formas de declarar arrays: usando la notación de corchetes ([]
) o la clase Array
.
-
Usando corchetes:
const nombreArray **:** tipo[] = [item1, item2, item3];
-
Usando la clase
Array
:const nombre-array : Array<tipo> = [item1, item2, item3]; // Array de strings
Ejemplo:
let numeros: number[] = [1, 2, 3]; // Array de numeros let nombres: Array<string> = ["Carlos", "Ana", "Luis"]; // Array de strings
Tuples
Las tuples son arrays con un número fijo de elementos de diferentes tipos. Esto permite representar datos más complejos de manera estructurada.
Para declarar una tuple, se utiliza la notación de corchetes ([]
) para especificar los tipos de cada elemento en la tuple:
const nombre-tuple: [tipo1, tipo2] = [item1, item2];
Ejemplo:
const persona: [string, number] = ["Carlos", 30]; // Tuple con un string y un number
🚨
- Arrays: Son colecciones de elementos del mismo tipo, y se pueden modificar dinámicamente (agregar y eliminar elementos).
- Tuples: Son arrays de longitud fija con tipos de datos diferentes en cada posición. Son útiles para representar estructuras de datos más complejas y están limitadas en cuanto a la modificación de su contenido.
Tipos Especiales
Tipo de Dato | Descripción | Ejemplo |
---|---|---|
any |
Permite almacenar cualquier tipo de valor. | let dato: any = "Hola"; |
void |
Tipo de retorno de funciones que no devuelven un valor. | function mostrarMensaje(): void { console.log("Hola"); } |
El tipo any
en TypeScript es un tipo especial que permite almacenar valores de cualquier tipo. Es útil en situaciones donde no se puede determinar el tipo de una variable en el momento de la escritura, o cuando se está trabajando con datos provenientes de fuentes externas, como APIs, donde los tipos pueden ser dinámicos o desconocidos.
Ventajas del tipo any
- Flexibilidad: Permite la asignación de diferentes tipos de datos a una variable sin restricciones.
- Interoperabilidad: Facilita la integración con bibliotecas JavaScript existentes donde los tipos pueden no estar claramente definidos.
Desventajas del tipo any
- Pérdida de Tipado Estático: Al usar
any
, se pierde gran parte de la ventaja que ofrece TypeScript, que es la verificación de tipos en tiempo de compilación. Esto puede llevar a errores en tiempo de ejecución que podrían haberse evitado con un tipado más estricto. - Menos Intellisense: La autocompletación y la asistencia del editor se ven reducidas al usar
any
, ya que TypeScript no puede inferir los métodos o propiedades disponibles. - Dificultad de Mantenimiento: El uso excesivo de
any
puede resultar en un código más difícil de leer y mantener, ya que no proporciona información clara sobre qué tipo de datos se espera.
🚨
¿Es mala práctica usar any
?
- Uso Moderado: Usar
any
ocasionalmente puede ser aceptable, especialmente en etapas tempranas de desarrollo o cuando se integra con librerías externas donde los tipos no están definidos. Sin embargo, debe ser un uso limitado. - Mejores Alternativas: En lugar de usar
any
, se recomienda utilizar tipos más específicos o, si es necesario, definir tipos personalizados que describan la estructura esperada de los datos.
Union Types
Los Union Types (tipos de unión) en TypeScript son una característica que permite a una variable aceptar múltiples tipos de datos. Esto significa que puedes definir un tipo que puede ser uno de varios tipos diferentes. Esto es útil cuando una variable puede tener diferentes tipos de valores en diferentes contextos.
La sintaxis para definir un Union Type utiliza el operador de pipe (|
).
let valor: string | number; // `valor` puede ser string o number
valor = "Hola"; // Válido
valor = 42; // También válido
// valor = true; // Error, ya que `boolean` no es parte del tipo
Ventajas de los Union Types
- Flexibilidad: Permiten que una variable tenga múltiples tipos, lo que es útil en situaciones donde los valores pueden variar.
- Claridad: Hacen explícito qué tipos son aceptables, lo que puede mejorar la legibilidad y mantenimiento del código.
- Tipo Seguro: Aumentan la seguridad del tipo al permitir que TypeScript verifique que solo se asignen valores de los tipos permitidos.
Alias de Tipo
Los alias de tipo son una forma de dar un nombre a un tipo que puede ser utilizado en varias partes de tu código. Esto es especialmente útil para simplificar tipos complejos o para dar un nombre más descriptivo a un tipo.
Para crear un alias de tipo, se utiliza la palabra clave type
seguida del nombre del alias y el tipo que deseas representar.
type NombreAlias = {
propiedad1: Tipo1;
propiedad2: Tipo2;
propiedadOpcional?: Tipo3; // Propiedad opcional
};
Ejemplo:
type Persona = {
nombre: string;
edad: number;
activo: boolean;
direccion?: string; // Propiedad opcional
};
let empleado: Persona = {
nombre: "Carlos",
edad: 37,
activo: true
};
Alias de Tipo con Unión
Los alias de tipo también se pueden utilizar para crear tipos de unión, lo que significa que un valor puede ser uno de varios tipos diferentes.
type ID = number | string;
let id1: ID = 123;
let id2: ID = "abc";
Tipos Literales
Un tipo literal restringe los valores posibles de una variable a un conjunto específico de valores. Es especialmente útil cuando quieres definir un conjunto limitado de valores válidos para una propiedad o variable.
type NombreTipoLiteral = "ValorLiteral1" | "ValorLiteral2" | "ValorLiteral3";
Ejemplo:
type Estado = "activo" | "inactivo" | "pendiente";
let estadoActual: Estado = "activo";
Combinación de Alias y Tipos Literales
Se pueden combinar alias de tipo con tipos literales para crear estructuras de datos más complejas.
Ejemplo:
type MetodoPago = "tarjeta" | "efectivo" | "transferencia";
type Pedido = {
id: number;
metodo: MetodoPago;
};
let pedido1: Pedido = {
id: 1,
metodo: "tarjeta"
};
pedido1.metodo = "bitcoin";
// Error: Type '"bitcoin"' is not assignable to type 'MetodoPago'.
Objetos
Un objeto en TypeScript se puede definir de manera similar a JavaScript, pero con la posibilidad de especificar los tipos de sus propiedades. Se pueden especificar los tipos de las propiedades de un objeto utilizando anotaciones de tipos. Esto asegura que las propiedades tengan los tipos correctos.
Sintaxis Básica
const persona: { propiedad1: Tipo1, propiedad2: Tipo2, propiedad3: Tipo3; } = {
propiedad1: Tipo1;
propiedad2: Tipo2;
propiedad3: Tipo3;
};
Ejemplo:
let persona: { nombre: string, edad: number, activo: boolean } = {
nombre: "Carlos",
edad: 30,
activo: true
};
Interfaces
Cuando se trabaja con objetos más complejos o cuando se quiere reutilizar la estructura de un objeto en varias partes del ódigo, es mejor usar interfaces. Una interface define la estructura de un objeto, lo que facilita la lectura y el mantenimiento del código.
interface NombreInterfaz {
propiedad1: Tipo1;
propiedad2: Tipo2;
propiedad3: Tipo3;
}
const nombreObjeto: NombreInterfaz = {
propiedad1: Tipo1;
propiedad2: Tipo2;
propiedad3: Tipo3;
}
Ejemplo:
interface Persona {
nombre: string;
edad: number;
activo: boolean;
}
const empleado: Persona = {
nombre: "Ana",
edad: 25,
activo: true
};
Propiedades de Solo Lectura (readonly
)
TypeScript permite declarar propiedades como de solo lectura utilizando la palabra clave readonly
. Esto significa que una vez asignado un valor a la propiedad, no puede cambiar.
Ejemplo:
interface Libro {
titulo: string;
readonly autor: string;
}
const libro: Libro = {
titulo: "El Quijote",
autor: "Miguel de Cervantes"
};
// libro.autor = "Otro autor"; // Error: No se puede modificar una propiedad readonly
Index Signatures
Los tipos de índice permiten que un objeto tenga un número dinámico de propiedades de tipos específicos. Es útil cuando no sabes cuántas propiedades tendrá un objeto, pero sí conoces el tipo de esas propiedades.
interface NombreInterfaz {
[clave: TipoClave]: TipoValor;
}
const nombreObjeto: NombreInterfaz = {
clave-TipoClave: TipoValor;
clave-TipoClave: TipoValor;
clave-TipoClave: TipoValor;
}
Ejemplo:
interface Diccionario {
[clave: string]: string;
}
let miDiccionario: Diccionario = {
casa: "house",
perro: "dog",
gato: "cat"
};
console.log(miDiccionario["casa"]); // "house"
Funciones
Al igual que en JavaScript, las funciones en TypeScript pueden aceptar parámetros, devolver valores y ser pasadas como argumentos a otras funciones. Sin embargo, TypeScript agrega características adicionales, como la capacidad de especificar tipos para los parámetros y el valor de retorno.
Sintaxis Básica
La sintaxis para declarar una función en TypeScript es similar a JavaScript, pero con la adición de tipos:
Función explícita
function nombreFuncion(parametro1: tipo1, parametro2: tipo2): tipoRetorno {
// Cuerpo de la función
}
Función Flecha
const nombreFuncion = (parametro1: tipo1, parametro2: tipo2): tipoRetorno => {
// Cuerpo de la función
};
Retorno de la Funciones
Tipo de Retorno | Descripción | Ejemplo |
---|---|---|
number | La función devuelve un número. | function add(x: number, y: number): number { return x + y; } |
string | La función devuelve una cadena de texto. | function greet(name: string): string { return "Hola, " + name; } |
boolean | La función devuelve un valor booleano (true o false). | function isEven(num: number): boolean { return num % 2 === 0; } |
void | La función no devuelve ningún valor. realiza acciones sin devolver un valor. | function log(message: string): void { console.log(message); } |
null | La función devuelve un valor nulo. | function getNull(): null { return null; } |
undefined | La función devuelve indefinido (puede ser implícito si no se retorna nada). | function doNothing(): undefined { } |
array | La función devuelve un arreglo de elementos de un tipo específico. | function getNumbers(): number[] { return [1, 2, 3]; } |
tupla | La función devuelve una tupla con elementos de diferentes tipos. | function getUser(): [string, number] { return ["Carlos", 30]; } |
object | La función devuelve un objeto con propiedades específicas. | function getUser(): { name: string; age: number } { return { name: "Carlos", age: 30 }; } |
unión | La función puede devolver más de un tipo | function getValue(isString: boolean): string |
interfaz | La función devuelve un objeto que cumple con una interfaz específica. | interface User { name: string; age: number; } function getUser(): User { return { name: "Carlos", age: 30 }; } |
Propiedades y Parámetros Opcionales
En TypeScript, el signo de interrogación (?
) se utiliza para declarar propiedades y parámetros opcionales. Esto permite que ciertos atributos de una clase o funciones no sean obligatorios, brindando mayor flexibilidad al trabajar con objetos y funciones.
Propiedades Opcionales
Al declarar una propiedad en una interfaz o clase, se puede usar el ?
para indicar que la propiedad es opcional. Esto significa que no es necesario proporcionar un valor para esa propiedad al crear una instancia del objeto. Si no se proporciona, el valor de la propiedad será undefined
.
Ejemplo:
interface Usuario {
nombre: string;
edad?: number; // Propiedad opcional
}
const usuario1: Usuario = { nombre: "Carlos" }; // edad es opcional
const usuario2: Usuario = { nombre: "Ana", edad: 25 }; // edad está presente
Parámetros Opcionales y Valores por Defecto
Los parámetros de una función también pueden ser marcados como opcionales usando ?
. Esto permite que la función se llame sin necesariamente proporcionar un argumento para ese parámetro.
Ejemplo:
function saludar(nombre: string, saludo?: string): string {
return `${saludo || "Hola"}, ${nombre}!`;
}
console.log(saludar("Carlos")); // "Hola, Carlos!"
console.log(saludar("Ana", "Buenos días")); // "Buenos días, Ana!"
También se puede proporcionar un valor por defecto a un parámetro:
function multiplicar(a: number, b: number = 1): number {
return a * b;
}
console.log(multiplicar(5)); // 5
console.log(multiplicar(5, 2)); // 10
Optional Chaining
El encadenamiento opcional (?.
) es una característica que permite acceder a propiedades de un objeto de forma segura, evitando errores si la propiedad es null
o undefined
. Si la propiedad no existe, se devuelve undefined
en lugar de lanzar un error.
Ejemplo:
const usuario = { nombre: "Carlos", direccion: { ciudad: "Madrid" } };
console.log(usuario.direccion?.ciudad); // "Madrid"
console.log(usuario.telefono?.numero); // undefined, no arroja error
El operador de coalescencia nula
Aunque no está directamente relacionado con el uso de ?
, el operador ??
se usa para asignar un valor por defecto si el valor de la izquierda es null
o undefined
.
const value = null;
const result = value ?? "Default Value"; // result será "Default Value"
Curso de TypeScript: Tipos Avanzados y Funciones