Top 20 Preguntas Frecuentes de TypeScript
Las 20 Preguntas Más Frecuentes de TypeScript
Section titled “Las 20 Preguntas Más Frecuentes de TypeScript”Preguntas de nivel intermedio que aparecen frecuentemente en entrevistas técnicas de TypeScript.
1. ¿Qué es TypeScript y qué ventajas ofrece sobre JavaScript?
Section titled “1. ¿Qué es TypeScript y qué ventajas ofrece sobre JavaScript?”Definición profesional: TypeScript es un superset de JavaScript con tipado estático opcional desarrollado por Microsoft. Transpila a JavaScript estándar y detecta errores en tiempo de compilación.
Ejemplo práctico:
// JavaScript - error en runtimefunction sumar(a, b) { return a + b;}sumar("5", 3); // "53" - error silencioso
// TypeScript - error en compilaciónfunction sumar(a: number, b: number): number { return a + b;}sumar("5", 3); // ❌ Error: Argument of type 'string' is not assignable to 'number'Cómo responder en entrevista:
“TypeScript añade tipado estático a JavaScript, detectando errores antes de ejecutar el código. Mejora el autocompletado, el refactoring y la mantenibilidad en proyectos grandes. Compila a JavaScript estándar, por lo que es compatible con cualquier entorno.”
2. ¿Qué son los tipos básicos y la inferencia de tipos?
Section titled “2. ¿Qué son los tipos básicos y la inferencia de tipos?”Definición profesional: TypeScript infiere el tipo de una variable automáticamente cuando se inicializa. Solo necesitas anotar tipos cuando la inferencia no puede determinarlo o cuando quieres ser explícito.
Ejemplo práctico:
// Inferencia automáticalet nombre = "Ana"; // infiere: stringlet edad = 30; // infiere: numberlet activo = true; // infiere: booleanlet lista = [1, 2, 3]; // infiere: number[]
// Anotación explícita cuando es necesariolet dato: string | number; // necesita anotación, no hay valor inicialdato = "texto";dato = 42;
// Tipos especialeslet cualquiera: any = "hola"; // ⚠️ Evitarlet seguro: unknown = "hola"; // ✅ Preferir
// void y neverfunction log(msg: string): void { console.log(msg); }function lanzar(msg: string): never { throw new Error(msg); }Cómo responder en entrevista:
“TypeScript infiere tipos automáticamente. Uso anotaciones explícitas solo cuando es necesario: variables sin valor inicial, parámetros de funciones, y tipos de retorno complejos. Prefiero unknown sobre any porque obliga a verificar el tipo antes de usarlo.”
3. ¿Cuándo usar interface vs type?
Section titled “3. ¿Cuándo usar interface vs type?”Definición profesional:
Ambos definen formas de objetos. interface soporta declaration merging y es ideal para contratos. type es más versátil para uniones, intersecciones y tipos complejos.
Ejemplo práctico:
// Interface - para contratos y objetos extendiblesinterface Animal { nombre: string; sonido(): string;}
interface Perro extends Animal { raza: string;}
// Declaration merging (solo con interface)interface Ventana { titulo: string;}interface Ventana { ancho: number; // Se fusiona automáticamente}
// Type - para tipos complejostype Estado = "activo" | "inactivo" | "pendiente"; // Unióntype PuntoXY = [number, number]; // Tuplatype Callback = (id: number) => Promise<void>; // Función
type PersonaConRol = Animal & { rol: string }; // IntersecciónCómo responder en entrevista:
“Interface para objetos y contratos de clase, type para uniones, tuplas y tipos complejos. En la práctica son muy similares para objetos, pero interface es preferida para APIs públicas por el declaration merging.”
4. ¿Cómo funcionan los Generics?
Section titled “4. ¿Cómo funcionan los Generics?”Definición profesional: Los genéricos crean componentes reutilizables que funcionan con múltiples tipos manteniendo la seguridad de tipos.
Ejemplo práctico:
// Función genéricafunction primero<T>(arr: T[]): T | undefined { return arr[0];}
const n = primero([1, 2, 3]); // tipo: number | undefinedconst s = primero(["a", "b"]); // tipo: string | undefined
// Restricción con extendsfunction longitud<T extends { length: number }>(valor: T): number { return valor.length;}
longitud("texto"); // 5 ✅longitud([1, 2, 3]); // 3 ✅// longitud(42); // ❌ number no tiene .length
// Genérico en interfazinterface Repositorio<T> { buscarPorId(id: number): Promise<T>; guardar(entidad: T): Promise<T>; eliminar(id: number): Promise<void>;}
interface Producto { id: number; nombre: string; }// class ProductoRepo implements Repositorio<Producto> { ... }Cómo responder en entrevista:
“Los genéricos permiten reutilizar lógica para distintos tipos sin perder la seguridad de tipos. Los uso en funciones utilitarias, interfaces de repositorios, y respuestas de API genéricas. Las restricciones con extends limitan qué tipos son aceptables.”
5. ¿Qué son los Union Types e Intersection Types?
Section titled “5. ¿Qué son los Union Types e Intersection Types?”Definición profesional:
Union (|) permite múltiples tipos posibles. Intersection (&) combina múltiples tipos en uno.
Ejemplo práctico:
// Union - puede ser uno u otrotype Resultado = string | number | null;
// Discriminated Union - patrón muy útiltype Figura = | { tipo: "circulo"; radio: number } | { tipo: "cuadrado"; lado: number } | { tipo: "rectangulo"; ancho: number; alto: number };
function area(figura: Figura): number { switch (figura.tipo) { case "circulo": return Math.PI * figura.radio ** 2; case "cuadrado": return figura.lado ** 2; case "rectangulo": return figura.ancho * figura.alto; }}
// Intersection - debe cumplir todos los tiposinterface Serializable { toJSON(): string; }interface Persistible { guardar(): Promise<void>; }
type Modelo = Serializable & Persistible;
// Objeto debe implementar ambas interfacesconst modelo: Modelo = { toJSON: () => "{}", guardar: async () => {}};Cómo responder en entrevista:
“Uso Union Types para valores que pueden ser de varios tipos y Discriminated Unions para modelar estados o variantes. Intersection Types los uso para combinar interfaces, similar a la herencia múltiple.”
6. ¿Qué es Type Narrowing?
Section titled “6. ¿Qué es Type Narrowing?”Definición profesional: Proceso por el cual TypeScript reduce el tipo de una variable dentro de un bloque, basándose en comprobaciones de tipo.
Ejemplo práctico:
function procesar(valor: string | number | null): string { // Null check if (valor === null) return "sin valor";
// typeof narrowing if (typeof valor === "string") { return valor.toUpperCase(); // TypeScript: string aquí }
return valor.toFixed(2); // TypeScript: number aquí}
// Type Guard personalizadointerface Gato { maullar(): void; }interface Perro { ladrar(): void; }
function esGato(animal: Gato | Perro): animal is Gato { return "maullar" in animal;}
function hacerSonido(animal: Gato | Perro): void { if (esGato(animal)) { animal.maullar(); // TypeScript: Gato aquí } else { animal.ladrar(); // TypeScript: Perro aquí }}Cómo responder en entrevista:
“TypeScript reduce el tipo posible dentro de condiciones usando typeof, instanceof, in, o Type Guards personalizados. Los Type Guards con valor is Tipo son muy útiles para narrowing de objetos.”
7. ¿Qué son los Utility Types más importantes?
Section titled “7. ¿Qué son los Utility Types más importantes?”Definición profesional: Tipos genéricos predefinidos que transforman tipos existentes para crear variantes sin duplicar código.
Ejemplo práctico:
interface Producto { id: number; nombre: string; precio: number; stock: number;}
// Partial - todas opcionales (para updates)type ActualizarProducto = Partial<Producto>;
// Required - todas obligatoriastype ProductoCompleto = Required<Partial<Producto>>;
// Pick - solo algunas propiedadestype ProductoResumen = Pick<Producto, "id" | "nombre">;
// Omit - todas menos algunastype ProductoSinStock = Omit<Producto, "stock">;
// Readonly - inmutabletype ProductoFijo = Readonly<Producto>;
// Record - diccionario tipadotype Inventario = Record<string, Producto>;
// ReturnType y Parametersfunction obtenerProducto(id: number): Producto { return { id, nombre: "Laptop", precio: 1000, stock: 5 };}type TipoRetorno = ReturnType<typeof obtenerProducto>; // Productotype TipoParams = Parameters<typeof obtenerProducto>; // [number]Cómo responder en entrevista:
“Los Utility Types más usados son Partial para updates parciales, Pick y Omit para crear subconjuntos, Readonly para inmutabilidad, y Record para diccionarios. ReturnType y Parameters son útiles para tipar funciones dinámicamente.”
8. ¿Cómo funcionan los Enums?
Section titled “8. ¿Cómo funcionan los Enums?”Definición profesional: Los Enums definen conjuntos de constantes con nombre. Los de string son preferidos porque son legibles en runtime.
Ejemplo práctico:
// Enum de string (preferido)enum EstadoOrden { Pendiente = "PENDIENTE", Pagado = "PAGADO", Enviado = "ENVIADO", Entregado = "ENTREGADO", Cancelado = "CANCELADO"}
function procesarOrden(estado: EstadoOrden): void { if (estado === EstadoOrden.Pagado) { console.log("Preparando envío..."); }}
procesarOrden(EstadoOrden.Pagado);
// const enum - se inlinea en compilación (más eficiente)const enum Permiso { Leer = "READ", Escribir = "WRITE", Admin = "ADMIN"}
// Alternativa con union de literales (sin overhead de objeto JS)type EstadoModerno = "pendiente" | "pagado" | "enviado" | "entregado";Cómo responder en entrevista:
“Los Enums de string son preferidos porque son legibles en runtime. const enum es más eficiente ya que se elimina en compilación. En proyectos modernos muchas veces prefiero union de literales como alternativa más ligera.”
9. ¿Qué son los Decoradores?
Section titled “9. ¿Qué son los Decoradores?”Definición profesional:
Funciones especiales que modifican clases, métodos o propiedades usando la sintaxis @decorador. Base de frameworks como Angular y NestJS.
Ejemplo práctico:
// Decorador de clasefunction Registrar(constructor: Function) { console.log(`Clase registrada: ${constructor.name}`);}
@Registrarclass Servicio { ejecutar() { return "ok"; }}
// Decorador de método con parámetrosfunction Validar(min: number, max: number) { return function (target: any, key: string, descriptor: PropertyDescriptor) { const original = descriptor.value; descriptor.value = function (valor: number) { if (valor < min || valor > max) { throw new Error(`${key}: valor ${valor} fuera de rango [${min}, ${max}]`); } return original.call(this, valor); }; };}
class Calculadora { @Validar(0, 100) aplicarDescuento(porcentaje: number): number { return porcentaje / 100; }}Cómo responder en entrevista:
“Los decoradores añaden comportamiento con @. Requieren experimentalDecorators: true en tsconfig. Son la base de Angular (@Component, @Injectable) y NestJS (@Controller, @Get). Los uso para logging, validación y metadatos.”
10. ¿Cómo funciona el tsconfig.json?
Section titled “10. ¿Cómo funciona el tsconfig.json?”Definición profesional: Archivo de configuración del compilador TypeScript que define target, rigor de tipado, resolución de módulos y estructura del proyecto.
Ejemplo práctico:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "strictNullChecks": true, "noImplicitAny": true, "noUnusedLocals": true, "noImplicitReturns": true, "rootDir": "./src", "outDir": "./dist", "moduleResolution": "node", "esModuleInterop": true, "sourceMap": true, "declaration": true, "experimentalDecorators": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts"]}Cómo responder en entrevista:
“strict: true activa todas las verificaciones. target define la versión de JS de salida. Siempre configuro rootDir y outDir para separar fuentes de compilados. En proyectos con NestJS agrego experimentalDecorators y emitDecoratorMetadata.”
11. ¿Qué son los Mapped Types?
Section titled “11. ¿Qué son los Mapped Types?”Definición profesional: Los Mapped Types crean nuevos tipos transformando las propiedades de un tipo existente, iterando sobre sus claves.
Ejemplo práctico:
// Mapped Type básicotype Opcional<T> = { [K in keyof T]?: T[K]; // Hace todas las propiedades opcionales};
// Similar a Partial<T>interface Usuario { id: number; nombre: string; email: string; }type UsuarioOpcional = Opcional<Usuario>;
// Readonly manualtype Inmutable<T> = { readonly [K in keyof T]: T[K];};
// Transformar tipos de propiedadestype Stringify<T> = { [K in keyof T]: string; // Convierte todas las propiedades a string};
type UsuarioString = Stringify<Usuario>;// { id: string; nombre: string; email: string }
// Con remapping (as) - TypeScript 4.1+type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];};
type UsuarioGetters = Getters<Usuario>;// { getId: () => number; getNombre: () => string; ... }Cómo responder en entrevista:
“Los Mapped Types iteran sobre las claves de un tipo para crear variantes. Son la base de Utility Types como Partial, Required y Readonly. Con la sintaxis as puedo renombrar propiedades al mapear.”
12. ¿Qué son los Conditional Types?
Section titled “12. ¿Qué son los Conditional Types?”Definición profesional: Los Conditional Types permiten crear tipos que dependen de una condición, similar a un operador ternario pero a nivel de tipos.
Ejemplo práctico:
// Tipo condicional básico: T extends U ? X : Ytype EsString<T> = T extends string ? "es string" : "no es string";
type R1 = EsString<string>; // "es string"type R2 = EsString<number>; // "no es string"
// NonNullable personalizadotype SinNulo<T> = T extends null | undefined ? never : T;type SoloString = SinNulo<string | null | undefined>; // string
// infer - extraer tipostype TipoRetorno<T> = T extends (...args: any[]) => infer R ? R : never;
function obtenerNombre(): string { return "Ana"; }type NombreTipo = TipoRetorno<typeof obtenerNombre>; // string
// Extraer tipo de Promisetype ResueltoComo<T> = T extends Promise<infer R> ? R : T;type DatoResuelto = ResueltoComo<Promise<number>>; // numbertype DatoDirecto = ResueltoComo<string>; // stringCómo responder en entrevista:
“Los Conditional Types son tipos ternarios: T extends U ? X : Y. Son la base de Utility Types como NonNullable y ReturnType. infer permite extraer tipos de posiciones específicas, muy útil para tipar funciones dinámicamente.”
13. ¿Qué son los Template Literal Types?
Section titled “13. ¿Qué son los Template Literal Types?”Definición profesional: Los Template Literal Types permiten construir tipos string combinando literales de tipo con sintaxis de template literals.
Ejemplo práctico:
// Template Literal Type básicotype Saludo = `Hola, ${string}`;const s1: Saludo = "Hola, Ana"; // ✅// const s2: Saludo = "Bye, Ana"; // ❌
// Combinando unionestype Color = "rojo" | "verde" | "azul";type Intensidad = "claro" | "oscuro";type ColorCompleto = `${Intensidad}-${Color}`;// "claro-rojo" | "claro-verde" | ... | "oscuro-azul"
// Patrones de eventostype Evento = "click" | "focus" | "blur";type HandlerEvento = `on${Capitalize<Evento>}`;// "onClick" | "onFocus" | "onBlur"
// Getters tipadosinterface Modelo { nombre: string; edad: number;}
type Getter<T extends object> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];};
type ModeloGetters = Getter<Modelo>;// { getNombre: () => string; getEdad: () => number }Cómo responder en entrevista:
“Los Template Literal Types construyen tipos string dinámicamente. Son muy útiles para tipar patrones como eventos (onClick, onFocus) o getters (getNombre, getEdad). Con Capitalize y otras helpers de string se pueden crear transformaciones de nombres automáticas.”
14. ¿Cómo tipar funciones y callbacks en TypeScript?
Section titled “14. ¿Cómo tipar funciones y callbacks en TypeScript?”Definición profesional: Las funciones en TypeScript se tipan con anotaciones de parámetros y retorno. Los callbacks se tipan con type o interface para mayor reutilización.
Ejemplo práctico:
// Función nombradafunction multiplicar(a: number, b: number): number { return a * b;}
// Arrow functionconst dividir = (a: number, b: number): number => a / b;
// Parámetros opcionales y por defectofunction saludar(nombre: string, titulo?: string, formal = false): string { return formal ? `${titulo} ${nombre}` : nombre;}
// Rest parametersfunction sumarTodo(...numeros: number[]): number { return numeros.reduce((acc, n) => acc + n, 0);}
// Sobrecarga de funcionesfunction combinar(a: string, b: string): string;function combinar(a: number, b: number): number;function combinar(a: any, b: any): any { return a + b;}
// Tipar callbackstype Predicado<T> = (elemento: T, indice: number) => boolean;
function filtrar<T>(arr: T[], fn: Predicado<T>): T[] { return arr.filter(fn);}
// Función asíncronaasync function obtenerDatos(url: string): Promise<string[]> { const res = await fetch(url); return res.json();}Cómo responder en entrevista:
“Tipo los parámetros y el retorno de las funciones explícitamente. Para callbacks uso type alias para reutilizarlos. La sobrecarga de funciones permite múltiples firmas para casos de uso distintos. Las funciones async siempre retornan
Promise<T>.”
15. ¿Cómo funcionan las clases en TypeScript?
Section titled “15. ¿Cómo funcionan las clases en TypeScript?”Definición profesional: TypeScript extiende las clases de JavaScript con modificadores de acceso, propiedades readonly, implementación de interfaces, y miembros abstractos.
Ejemplo práctico:
// Clase con modificadores de accesoclass CuentaBancaria { private saldo: number; readonly numeroCuenta: string; protected titular: string;
constructor(numeroCuenta: string, titular: string, saldoInicial: number) { this.numeroCuenta = numeroCuenta; this.titular = titular; this.saldo = saldoInicial; }
depositar(monto: number): void { if (monto <= 0) throw new Error("Monto debe ser positivo"); this.saldo += monto; }
get saldoActual(): number { return this.saldo; }}
// Implementar interfazinterface Serializable { toJSON(): string;}
class Producto implements Serializable { constructor( public readonly id: number, public nombre: string, private precio: number ) {}
toJSON(): string { return JSON.stringify({ id: this.id, nombre: this.nombre }); }}
// Clase abstractaabstract class Figura { abstract area(): number; abstract perimetro(): number;
describir(): string { return `Área: ${this.area()}, Perímetro: ${this.perimetro()}`; }}
class Circulo extends Figura { constructor(private radio: number) { super(); } area(): number { return Math.PI * this.radio ** 2; } perimetro(): number { return 2 * Math.PI * this.radio; }}Cómo responder en entrevista:
“TypeScript añade private, protected, public y readonly a las clases JS. El constructor shorthand permite declarar propiedades directamente en los parámetros. Las clases pueden implementar interfaces y extender clases abstractas.”
16. ¿Qué son los Namespaces y Módulos?
Section titled “16. ¿Qué son los Namespaces y Módulos?”Definición profesional: Los módulos (ES Modules) son el sistema estándar para organizar código en TypeScript. Los Namespaces son una alternativa antigua que agrupa código bajo un nombre global, hoy en desuso.
Ejemplo práctico:
// Módulos ES (sistema recomendado)// math.tsexport function sumar(a: number, b: number): number { return a + b;}
export interface Calculadora { operacion: string; ejecutar(a: number, b: number): number;}
export default class Calculadora { /* ... */ }
// main.tsimport Calculadora, { sumar, type Calculadora as ICalculadora } from "./math";import * as Math from "./math"; // Importar todo el módulo
// Declaración de tipos para módulos JS externos// archivo: typings.d.tsdeclare module "mi-libreria-sin-tipos" { export function metodo(config: object): void; export const version: string;}
// Namespace (legacy, evitar en código nuevo)namespace Validaciones { export function esEmail(valor: string): boolean { return /^[^s@]+@[^s@]+.[^s@]+$/.test(valor); }}
const valido = Validaciones.esEmail("test@test.com");Cómo responder en entrevista:
“Los módulos ES son el estándar moderno en TypeScript. Los Namespaces son legacy y se evitan en código nuevo. Para librerías JS sin tipos, creo archivos .d.ts con declare module.”
17. ¿Cómo usar TypeScript con APIs asíncronas?
Section titled “17. ¿Cómo usar TypeScript con APIs asíncronas?”Definición profesional: TypeScript tipado con Promises, async/await y el manejo de errores asíncronos para garantizar seguridad de tipos en operaciones asíncronas.
Ejemplo práctico:
// Interfaz del modelointerface Usuario { id: number; nombre: string; email: string;}
// Función asíncrona tipadaasync function obtenerUsuario(id: number): Promise<Usuario> { const response = await fetch(`/api/usuarios/${id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json() as Promise<Usuario>;}
// Manejo de errores tipadotype Resultado<T, E = Error> = | { ok: true; valor: T } | { ok: false; error: E };
async function intentar<T>(fn: () => Promise<T>): Promise<Resultado<T>> { try { return { ok: true, valor: await fn() }; } catch (error) { return { ok: false, error: error instanceof Error ? error : new Error(String(error)) }; }}
// Usoasync function main() { const resultado = await intentar(() => obtenerUsuario(1)); if (resultado.ok) { console.log(resultado.valor.nombre); // TypeScript: Usuario aquí } else { console.error(resultado.error.message); }}Cómo responder en entrevista:
“Las funciones async retornan
Promise<T>. Uso el tipo genérico de respuestaResultado<T, E>para manejar errores sin excepciones. El cast asPromise<T>al hacer fetch permite tipar la respuesta, aunque en producción combino con validación de esquema (zod, class-validator).“
18. ¿Qué son los Declaration Files (.d.ts)?
Section titled “18. ¿Qué son los Declaration Files (.d.ts)?”Definición profesional:
Los archivos .d.ts son archivos de solo declaración de tipos. Permiten añadir tipado TypeScript a librerías JavaScript sin modificar su código fuente.
Ejemplo práctico:
// mi-libreria.d.ts - Declaraciones de tipos para una librería JS
// Declarar módulo completodeclare module "mi-libreria" { // Función exportada export function formatearFecha(fecha: Date, formato: string): string;
// Interfaz exportada export interface OpcionesFormato { locale?: string; timezone?: string; }
// Clase exportada export class Formateador { constructor(opciones?: OpcionesFormato); formatear(valor: any): string; }
// Export default const defecto: Formateador; export default defecto;}
// Augmentación de módulos existentes// Añadir método a String sin modificar la libreríadeclare global { interface String { toTitleCase(): string; } interface Window { miPlugin: { version: string }; }}
// Variables globalesdeclare const __VERSION__: string;declare const __DEV__: boolean;Cómo responder en entrevista:
“Los archivos .d.ts contienen solo declaraciones de tipos sin implementación. Se usan para tipar librerías JS. @types/nombreLibreria en npm son paquetes de declaraciones de tipos de la comunidad. Para librerías sin @types, creo mis propios .d.ts.”
19. ¿Cómo hacer Type Assertions y cuándo usarlas?
Section titled “19. ¿Cómo hacer Type Assertions y cuándo usarlas?”Definición profesional:
Las Type Assertions (as T o <T>) son instrucciones para decirle al compilador que trate un valor como un tipo específico, sobreescribiendo la inferencia. Deben usarse con precaución.
Ejemplo práctico:
// Type assertion con "as"const input = document.getElementById("nombre") as HTMLInputElement;console.log(input.value); // TypeScript sabe que es HTMLInputElement
// Sin assertion: document.getElementById retorna HTMLElement | null// y HTMLElement no tiene .value
// Double assertion (cuando los tipos son muy diferentes)const valor = "42" as unknown as number; // ⚠️ Usar solo en casos extremos
// Non-null assertion operator (!)function obtenerElemento(id: string): HTMLElement { const el = document.getElementById(id); return el!; // Le dice a TS: "confía en mí, no es null" // ⚠️ Úsalo solo cuando sabes con certeza que no es null}
// Mejor alternativa: verificar antesfunction obtenerElementoSeguro(id: string): HTMLElement { const el = document.getElementById(id); if (!el) throw new Error(`Elemento #${id} no encontrado`); return el; // TypeScript: HTMLElement (narrowed)}
// satisfies operator (TS 4.9+) - verifica sin cambiar el tipo inferidoconst config = { host: "localhost", port: 3000} satisfies Record<string, string | number>;
// config.host es string (no string | number)Cómo responder en entrevista:
“Las Type Assertions con as le dicen al compilador el tipo que esperamos. Las uso para resultados del DOM donde conozco el tipo exacto. El operador ! para non-null debo usarlo solo cuando estoy seguro que el valor existe. El operador satisfies de TS 4.9 es más seguro porque valida sin perder la inferencia.”
20. ¿Cómo integrar TypeScript en un proyecto real?
Section titled “20. ¿Cómo integrar TypeScript en un proyecto real?”Definición profesional: La integración de TypeScript en proyectos reales implica configuración de tsconfig, instalación de tipos (@types), integración con linters (ESLint), y estrategias de migración desde JavaScript.
Ejemplo práctico:
// 1. Inicializar proyecto TypeScript// npm init -y// npm install typescript @types/node --save-dev// npx tsc --init
// 2. tsconfig.json para proyecto Node.js// {// "compilerOptions": {// "target": "ES2020", "module": "commonjs",// "strict": true, "outDir": "dist", "rootDir": "src"// }// }
// 3. package.json scripts// "scripts": {// "build": "tsc",// "dev": "ts-node src/index.ts",// "watch": "tsc --watch"// }
// 4. ESLint con TypeScript// npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev// .eslintrc.js:// {// "parser": "@typescript-eslint/parser",// "plugins": ["@typescript-eslint"],// "extends": ["plugin:@typescript-eslint/recommended"]// }
// 5. Migración gradual de JS a TS// En tsconfig.json para migración progresiva:// "allowJs": true, // Permite archivos .js junto a .ts// "checkJs": true, // Chequea también los .js// "noImplicitAny": false // Menos estricto al inicio
// 6. Estructura de proyecto recomendada// src/// models/ (interfaces y tipos)// services/ (lógica de negocio)// controllers/ (endpoints)// utils/ (funciones utilitarias)// types/ (tipos compartidos, .d.ts)// dist/ (JS compilado)// tsconfig.jsonCómo responder en entrevista:
“Para un proyecto nuevo instalo typescript y ejecuto tsc —init, activo strict: true, y configuro rootDir/outDir. Para proyectos existentes uso allowJs para migración gradual. Siempre integro ESLint con @typescript-eslint para mantener consistencia de código.”