InterviewHack.ai
Start free
Blog/Preguntas de entrevista de TypeScript con respuestas (45+)

Preguntas de entrevista de TypeScript con respuestas (45+)

16 de septiembre de 2026

typescriptentrevista técnica

Las 45+ preguntas de TypeScript más frecuentes en entrevistas técnicas, con respuestas detalladas y código real. De junior a senior, en español.

Si estás preparando una entrevista técnica donde TypeScript es parte del stack, esta guía es tu punto de partida. Acá no vas a encontrar definiciones copiadas de la documentación oficial — vas a encontrar las preguntas que realmente caen, con respuestas explicadas como si estuvieras hablando con un colega senior que ya pasó por eso.

La guía cubre desde conceptos fundamentales hasta temas avanzados como tipos condicionales, decoradores y performance de compilación. Ordenadas por nivel de dificultad para que puedas usarlas como checklist.


Conceptos fundamentales (junior)

1. ¿Qué es TypeScript y por qué existe?

TypeScript es un superset de JavaScript que agrega tipado estático opcional. Compila a JavaScript puro y puede correr en cualquier entorno donde corra JS.

Existe porque JavaScript escala mal en equipos grandes. Sin tipos, refactorizar una función que se usa en 40 archivos es un juego de ruleta rusa. TypeScript le da al IDE (y a vos) información suficiente para que ese refactor sea seguro.

ts
// JavaScript: sabés qué es user solo si lo buscás
function getFullName(user) {
  return user.firstName + " " + user.lastName;
}

// TypeScript: el contrato está explícito
function getFullName(user: { firstName: string; lastName: string }): string {
  return user.firstName + " " + user.lastName;
}

2. ¿Cuál es la diferencia entre `type` e `interface`?

Ambas definen la forma de un objeto, pero tienen diferencias importantes:

  • interface se puede extender con extends y se puede "reabrir" (declaración múltiple se fusiona)
  • type es más flexible: puede definir uniones, intersecciones, tuplas y tipos primitivos
  • Para objetos simples que otros van a extender, interface es la convención
  • Para uniones o tipos complejos, necesitás type
ts
// Interface — se puede extender y reabrir
interface Animal {
  nombre: string;
}
interface Animal {
  edad: number; // se fusiona con la anterior
}

// Type — más expresivo para uniones
type Resultado = "ok" | "error" | "pendiente";
type Coordenada = [number, number];
type Usuario = { id: number } & { nombre: string }; // intersección

En una entrevista: mencioná que en la práctica la diferencia es menor, pero que uses interface para APIs públicas de librerías (permite extensión por el consumidor) y type para lógica interna compleja.

3. ¿Qué es `any` y por qué hay que evitarlo?

any desactiva el chequeo de tipos para esa variable. Es la puerta de escape del sistema de tipos — y una bomba de tiempo.

ts
let data: any = fetchData();
data.metodoQueNoExiste(); // TypeScript no avisa — error en runtime

Alternativas más seguras:

  • unknown: igual de flexible, pero forzás un type-check antes de usarlo
  • object: si solo necesitás saber que no es primitivo
  • Un tipo genérico : si el tipo varía pero querés mantenerte seguro
ts
function procesar(input: unknown) {
  if (typeof input === "string") {
    console.log(input.toUpperCase()); // ahora sí es seguro
  }
}

4. ¿Qué es `unknown` y en qué se diferencia de `any`?

unknown es el tipo seguro para "no sé qué es esto todavía". A diferencia de any, TypeScript te obliga a narrowear (acotar) el tipo antes de usarlo.

ts
const valor: unknown = JSON.parse(respuesta);

// Error: no podés llamar métodos sin verificar
// valor.toUpperCase(); ❌

if (typeof valor === "string") {
  valor.toUpperCase(); // ✓
}

Usá unknown en los bordes del sistema: respuestas de APIs externas, datos de formularios, resultados de JSON.parse.

5. ¿Qué es un union type?

Un tipo que puede ser uno de varios tipos posibles, separados por |.

ts
type Estado = "activo" | "inactivo" | "pendiente";
type IdONombre = number | string;

function buscarUsuario(id: IdONombre) {
  if (typeof id === "number") {
    return db.buscarPorId(id);
  }
  return db.buscarPorNombre(id);
}

6. ¿Qué es un intersection type?

Combina múltiples tipos en uno que tiene todas las propiedades de todos. Se usa &.

ts
type Persona = { nombre: string; edad: number };
type Empleado = { empresa: string; cargo: string };

type EmpleadoCompleto = Persona & Empleado;
// Tiene: nombre, edad, empresa, cargo

const empleado: EmpleadoCompleto = {
  nombre: "Ana",
  edad: 28,
  empresa: "Acme",
  cargo: "Dev",
};

7. ¿Qué son los literal types?

Permiten que una variable solo acepte valores específicos, no solo un tipo general.

ts
type Direccion = "norte" | "sur" | "este" | "oeste";
type PuertoHTTP = 80 | 443 | 8080;

function mover(direccion: Direccion, pasos: number) {
  // solo acepta los 4 strings exactos
}

mover("norte", 3); // ✓
mover("arriba", 3); // Error ❌

8. ¿Qué es `null` vs `undefined` en TypeScript?

Por defecto (con strictNullChecks: true), son tipos separados y no asignables a otros tipos sin ser explícito.

ts
let nombre: string = null; // Error ❌
let nombre: string | null = null; // ✓

// El operador ?. (optional chaining) maneja el caso null/undefined
const largo = usuario?.nombre?.length;

// El operador ?? (nullish coalescing) da un default solo para null/undefined
const display = nombre ?? "Anónimo";

9. ¿Qué hace el operador `as`?

Es un type assertion — le decís a TypeScript "confiame, yo sé que esto es de este tipo". No convierte el valor, solo convence al compilador.

ts
const input = document.getElementById("nombre") as HTMLInputElement;
console.log(input.value); // TypeScript ya sabe que tiene .value

Cuidado: si la aserción es incorrecta, el error ocurre en runtime. Usalo solo cuando vos tenés más contexto que el compilador.

10. ¿Qué es `readonly`?

Marca una propiedad como solo lectura — se puede asignar una vez (al inicializar) pero no se puede modificar después.

ts
interface Config {
  readonly apiUrl: string;
  readonly version: number;
}

const config: Config = { apiUrl: "https://api.ejemplo.com", version: 2 };
config.apiUrl = "otro"; // Error ❌

Tipos avanzados (semi-senior)

11. ¿Qué son los generics?

Permiten escribir código que funciona con distintos tipos sin perder type safety. En lugar de hardcodear un tipo, usás un "parámetro de tipo".

ts
// Sin generics: perdés tipos o repetís código
function primero(arr: number[]): number { return arr[0]; }
function primeroString(arr: string[]): string { return arr[0]; }

// Con generics: una sola función, type-safe
function primero<T>(arr: T[]): T {
  return arr[0];
}

const n = primero([1, 2, 3]); // TypeScript infiere: number
const s = primero(["a", "b"]); // TypeScript infiere: string

12. ¿Qué son los utility types?

Tipos genéricos incluidos en TypeScript que transforman otros tipos. Los más usados:

ts
interface Usuario {
  id: number;
  nombre: string;
  email: string;
  password: string;
}

// Partial — todas las props opcionales (útil para updates parciales)
type ActualizarUsuario = Partial<Usuario>;
// { id?: number; nombre?: string; email?: string; password?: string }

// Required — todas las props obligatorias
type UsuarioCompleto = Required<Usuario>;

// Pick — solo algunas props
type UsuarioPublico = Pick<Usuario, "id" | "nombre">;
// { id: number; nombre: string }

// Omit — todo menos algunas props
type UsuarioSinPassword = Omit<Usuario, "password">;

// Readonly — props inmutables
type UsuarioFijo = Readonly<Usuario>;

// Record — mapa de clave-valor tipado
type PermisosPorRol = Record<"admin" | "user" | "guest", boolean[]>;

13. ¿Qué es `keyof`?

Devuelve una unión con las claves de un tipo.

ts
interface Producto {
  nombre: string;
  precio: number;
  stock: number;
}

type ClavesProducto = keyof Producto; // "nombre" | "precio" | "stock"

function obtenerPropiedad<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const p: Producto = { nombre: "Mate", precio: 500, stock: 10 };
const precio = obtenerPropiedad(p, "precio"); // TypeScript sabe que es number

14. ¿Qué es `typeof` en contexto de tipos?

En runtime es el operador de JavaScript. Pero en un contexto de tipo, extrae el tipo de una variable o valor.

ts
const config = {
  endpoint: "https://api.com",
  timeout: 5000,
  retries: 3,
};

type Config = typeof config;
// { endpoint: string; timeout: number; retries: number }

function resetear(cfg: typeof config) {
  // cfg tiene exactamente la misma forma
}

15. ¿Qué son los mapped types?

Crean nuevos tipos transformando cada propiedad de un tipo existente.

ts
// Implementación manual de Partial:
type MiPartial<T> = {
  [K in keyof T]?: T[K];
};

// Implementación manual de Readonly:
type MiReadonly<T> = {
  readonly [K in keyof T]: T[K];
};

// Transformación custom: hacer todas las props string
type Stringify<T> = {
  [K in keyof T]: string;
};

type UsuarioComoString = Stringify<{ id: number; nombre: string }>;
// { id: string; nombre: string }

16. ¿Qué son los conditional types?

Permiten tipos que cambian según una condición, con la sintaxis T extends U ? X : Y.

ts
type EsString<T> = T extends string ? "sí" : "no";

type R1 = EsString<string>; // "sí"
type R2 = EsString<number>; // "no"

// Ejemplo útil: extraer el tipo de retorno de una función
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function obtenerUsuario(): { id: number; nombre: string } {
  return { id: 1, nombre: "Ana" };
}

type UsuarioRetorno = ReturnType<typeof obtenerUsuario>;
// { id: number; nombre: string }

17. ¿Qué es `infer`?

Se usa dentro de conditional types para capturar y nombrar un tipo que TypeScript infiere.

ts
// Extraer el tipo de elemento de un array
type ElementType<T> = T extends (infer E)[] ? E : never;

type ElemString = ElementType<string[]>; // string
type ElemNum = ElementType<number[]>; // number

// Extraer el primer parámetro de una función
type PrimerParam<T> = T extends (first: infer P, ...rest: any[]) => any ? P : never;

type P = PrimerParam<(id: number, nombre: string) => void>; // number

18. ¿Qué son los template literal types?

Desde TypeScript 4.1, podés construir tipos de string con interpolación, igual que los template literals de JS.

ts
type Evento = "click" | "focus" | "blur";
type ManejadorEvento = `on${Capitalize<Evento>}`;
// "onClick" | "onFocus" | "onBlur"

// Útil para tipear propiedades CSS o rutas de API
type Ruta = "/usuarios" | "/productos";
type RutaConId = `${Ruta}/${number}`;
// "/usuarios/${number}" | "/productos/${number}"

19. ¿Qué es `never`?

Representa un tipo que nunca puede tener un valor. Aparece en:

  • Funciones que siempre lanzan excepciones
  • Funciones con loops infinitos
  • Ramas de código inalcanzables (exhaustive checks)
ts
function lanzarError(msg: string): never {
  throw new Error(msg);
  // TypeScript sabe que nunca hay retorno normal
}

// Uso para exhaustive check en switch:
type Forma = "circulo" | "cuadrado" | "triangulo";

function calcularArea(forma: Forma): number {
  switch (forma) {
    case "circulo": return Math.PI * 10;
    case "cuadrado": return 100;
    case "triangulo": return 50;
    default:
      const _check: never = forma; // Error si falta un caso
      return _check;
  }
}

20. ¿Qué es el type narrowing?

Es cuando TypeScript reduce el tipo posible de una variable dentro de un bloque, basándose en verificaciones.

ts
function formatear(valor: string | number) {
  if (typeof valor === "string") {
    // Acá TypeScript sabe que es string
    return valor.toUpperCase();
  }
  // Acá sabe que es number
  return valor.toFixed(2);
}

// Con instanceof
function manejarError(e: unknown) {
  if (e instanceof Error) {
    console.log(e.message); // TypeScript sabe que tiene .message
  }
}

// Con type guards personalizados
function esUsuario(obj: unknown): obj is { nombre: string } {
  return typeof obj === "object" && obj !== null && "nombre" in obj;
}

Clases y programación orientada a objetos

21. ¿Cómo se tipean las clases en TypeScript?

ts
class CuentaBancaria {
  private saldo: number;
  readonly titular: string;
  protected banco: string;

  constructor(titular: string, banco: string, saldoInicial: number) {
    this.titular = titular;
    this.banco = banco;
    this.saldo = saldoInicial;
  }

  depositar(monto: number): void {
    if (monto <= 0) throw new Error("Monto inválido");
    this.saldo += monto;
  }

  obtenerSaldo(): number {
    return this.saldo;
  }
}

const cuenta = new CuentaBancaria("Ana", "Galicia", 1000);
cuenta.depositar(500);
console.log(cuenta.obtenerSaldo()); // 1500
cuenta.saldo; // Error: es private ❌

22. ¿Qué son los abstract classes?

Clases que no se pueden instanciar directamente pero definen un contrato para sus subclases.

ts
abstract class Notificador {
  abstract enviar(mensaje: string): Promise<void>;

  async notificarConLog(mensaje: string): Promise<void> {
    console.log(`Enviando: ${mensaje}`);
    await this.enviar(mensaje); // llama a la implementación concreta
    console.log("Enviado ✓");
  }
}

class NotificadorEmail extends Notificador {
  async enviar(mensaje: string): Promise<void> {
    // lógica de envío de email
  }
}

class NotificadorSMS extends Notificador {
  async enviar(mensaje: string): Promise<void> {
    // lógica de envío de SMS
  }
}

// new Notificador(); // Error ❌
const email = new NotificadorEmail();
await email.notificarConLog("Código: 1234");

23. ¿Diferencia entre `implements` y `extends`?

  • extends: hereda de otra clase (herencia). La subclase obtiene métodos y propiedades.
  • implements: cumple el contrato de una interfaz. No hereda implementación.
ts
interface Serializable {
  serializar(): string;
}

class Base {
  id: number = 0;
}

class Entidad extends Base implements Serializable {
  nombre: string = "";

  serializar(): string {
    return JSON.stringify({ id: this.id, nombre: this.nombre });
  }
}

Funciones y tipado avanzado

24. ¿Cómo se tipean las funciones?

ts
// Forma básica
function sumar(a: number, b: number): number {
  return a + b;
}

// Arrow function tipada
const multiplicar: (a: number, b: number) => number = (a, b) => a * b;

// Parámetros opcionales y con default
function saludar(nombre: string, titulo?: string, idioma: string = "es"): string {
  const t = titulo ? `${titulo} ` : "";
  return `Hola, ${t}${nombre}`;
}

// Rest params
function sumarTodos(...numeros: number[]): number {
  return numeros.reduce((acc, n) => acc + n, 0);
}

// Function overloads
function combinar(a: string, b: string): string;
function combinar(a: number, b: number): number;
function combinar(a: any, b: any) {
  return a + b;
}

25. ¿Qué son los decoradores?

Funciones que modifican clases, métodos, propiedades o parámetros. Necesitan experimentalDecorators: true en tsconfig.json.

ts
// Decorador de clase: agrega funcionalidad a la clase
function Singleton<T extends new (...args: any[]) => {}>(constructor: T) {
  let instance: InstanceType<T>;
  return class extends constructor {
    constructor(...args: any[]) {
      if (instance) return instance;
      super(...args);
      instance = this as unknown as InstanceType<T>;
    }
  };
}

// Decorador de método: mide el tiempo de ejecución
function Medir(target: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  descriptor.value = function (...args: any[]) {
    const inicio = performance.now();
    const resultado = original.apply(this, args);
    console.log(`${key} tardó ${performance.now() - inicio}ms`);
    return resultado;
  };
  return descriptor;
}

class ServicioUsuarios {
  @Medir
  buscar(id: number) {
    // ...
  }
}

26. ¿Qué es un type guard?

Una función que retorna valor is Tipo — le dice a TypeScript que si retorna true, el argumento es de ese tipo.

ts
interface Perro { ladrar(): void; raza: string; }
interface Gato { maullar(): void; color: string; }

function esPerro(animal: Perro | Gato): animal is Perro {
  return "ladrar" in animal;
}

function hacerSonido(animal: Perro | Gato) {
  if (esPerro(animal)) {
    animal.ladrar(); // TypeScript sabe que es Perro
  } else {
    animal.maullar(); // TypeScript sabe que es Gato
  }
}

Módulos, configuración y ecosistema

27. ¿Qué es `tsconfig.json` y cuáles son las opciones más importantes?

json
{
  "compilerOptions": {
    "target": "ES2020",         // qué versión de JS genera
    "module": "ESNext",         // sistema de módulos
    "lib": ["ES2020", "DOM"],   // definiciones de tipos disponibles
    "strict": true,             // activa todas las verificaciones estrictas
    "noImplicitAny": true,      // error si infiere `any`
    "strictNullChecks": true,   // null/undefined no son asignables sin explicitar
    "esModuleInterop": true,    // mejor compatibilidad con módulos CommonJS
    "outDir": "./dist",         // dónde van los archivos compilados
    "rootDir": "./src",         // dónde está el fuente
    "paths": {                  // aliases de imports
      "@/*": ["./src/*"]
    }
  }
}

Siempre activá strict: true. En un proyecto heredado, activá las opciones de a una.

28. ¿Qué son los declaration files (.d.ts)?

Archivos que solo contienen tipos, sin implementación. Sirven para tipar librerías JavaScript que no tienen TypeScript nativo.

ts
// milibreria.d.ts
declare module "milibreria" {
  export function calcular(input: number): number;
  export interface Opciones {
    precision: number;
    modo: "rapido" | "preciso";
  }
}

La mayoría de las librerías populares tienen tipos en @types/nombre-librería (DefinitelyTyped).

29. ¿Qué es el modo strict?

Activa un conjunto de verificaciones más estrictas:

  • noImplicitAny: error si TypeScript infiere any
  • strictNullChecks: null y undefined son tipos separados
  • strictFunctionTypes: chequeo más preciso de tipos de funciones
  • strictBindCallApply: tipado correcto de .bind(), .call(), .apply()
  • strictPropertyInitialization: propiedades de clase deben inicializarse

Respuesta de entrevista: "En proyectos nuevos siempre activo strict. En proyectos legacy lo habilito incrementalmente, empezando por noImplicitAny porque es el que más bugs encuentra."

30. ¿Cómo funciona el type inference?

TypeScript puede inferir tipos sin que los declares explícitamente.

ts
// TypeScript infiere: number
const edad = 25;

// TypeScript infiere: string[]
const nombres = ["Ana", "Juan", "Pedro"];

// TypeScript infiere el tipo de retorno
function doblar(n: number) {
  return n * 2; // infiere: number
}

// TypeScript infiere en desestructuración
const { nombre, edad: años } = { nombre: "Ana", edad: 28 };
// nombre: string, años: number

Declarás tipos explícitamente cuando la inferencia no tiene suficiente información (parámetros de función, variables sin inicializar) o cuando querés un tipo más específico.


Preguntas de nivel senior

31. ¿Qué es un discriminated union y cuándo usarlo?

Un pattern donde todos los tipos de una unión tienen una propiedad "discriminante" (literal type) que permite narrowear con seguridad.

ts
type Cargando = { estado: "cargando" };
type Exitoso = { estado: "exitoso"; datos: string[] };
type Fallido = { estado: "fallido"; error: string };

type EstadoPeticion = Cargando | Exitoso | Fallido;

function renderizar(estado: EstadoPeticion) {
  switch (estado.estado) {
    case "cargando":
      return "<Spinner />";
    case "exitoso":
      return estado.datos.join(", "); // TypeScript sabe que .datos existe
    case "fallido":
      return `Error: ${estado.error}`; // TypeScript sabe que .error existe
  }
}

Es el patrón favorito para modelar estados de UI, resultados de operaciones async y eventos de dominio.

32. ¿Qué son los branded types y para qué sirven?

Sirven para diferenciar tipos que estructuralmente son iguales pero semánticamente distintos. Evitan que mezcles accidentalmente un ID de usuario con un ID de producto.

ts
type Brand<T, B> = T & { readonly __brand: B };

type UserId = Brand<number, "UserId">;
type ProductId = Brand<number, "ProductId">;

// Función constructora que "acuña" el tipo
function asUserId(id: number): UserId {
  return id as UserId;
}

function buscarUsuario(id: UserId) { /* ... */ }
function buscarProducto(id: ProductId) { /* ... */ }

const uid = asUserId(42);
buscarUsuario(uid); // ✓
buscarProducto(uid); // Error ❌ — no es un ProductId

33. ¿Cómo tiparías un fetch genérico?

ts
async function fetchJson<T>(url: string): Promise<T> {
  const res = await fetch(url);
  if (!res.ok) {
    throw new Error(`HTTP ${res.status}: ${res.statusText}`);
  }
  return res.json() as Promise<T>;
}

// Uso
interface Usuario {
  id: number;
  nombre: string;
}

const usuario = await fetchJson<Usuario>("/api/usuarios/1");
console.log(usuario.nombre); // TypeScript sabe que es string

Nota de entrevista: el as Promise es una aserción — res.json() retorna any. Para máxima seguridad en producción, validarías con una librería como Zod.

34. ¿Cómo funcionan los recursive types?

Tipos que se referencian a sí mismos. Necesarios para estructuras de árbol, JSON, componentes anidados.

ts
// Tipo JSON
type JSONValue =
  | string
  | number
  | boolean
  | null
  | JSONValue[]
  | { [key: string]: JSONValue };

// Árbol
interface Nodo<T> {
  valor: T;
  hijos: Nodo<T>[];
}

// Menú anidado
interface MenuItem {
  label: string;
  url?: string;
  submenu?: MenuItem[]; // referencia a sí mismo
}

35. ¿Qué es `satisfies`? (TypeScript 4.9+)

Permite verificar que un valor satisface un tipo, sin que ese tipo reemplace la inferencia más específica.

ts
type Paleta = {
  rojo: string | [number, number, number];
  azul: string | [number, number, number];
};

// Con satisfies: TypeScript valida el contrato pero mantiene los tipos inferidos
const colores = {
  rojo: [255, 0, 0],
  azul: "#0000FF",
} satisfies Paleta;

colores.rojo[0]; // ✓ — TypeScript sabe que es number[] (no string | number[])
colores.azul.toUpperCase(); // ✓ — TypeScript sabe que es string (no string | number[])

Sin satisfies, con una anotación de tipo directa const colores: Paleta = ..., TypeScript inferiría los tipos más amplios y perderías esa precisión.

36. ¿Qué es `Awaited<T>`?

Extrae el tipo resuelto de una Promise, recursivamente.

ts
type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<number>>>; // number

// Muy útil con funciones async
async function fetchUsuario() {
  return { id: 1, nombre: "Ana" };
}

type Usuario = Awaited<ReturnType<typeof fetchUsuario>>;
// { id: number; nombre: string }

37. ¿Cómo se implementa el patrón Builder con tipos?

ts
class QueryBuilder<T extends object> {
  private filters: Partial<T> = {};
  private limitVal?: number;

  where<K extends keyof T>(key: K, value: T[K]): this {
    this.filters[key] = value;
    return this;
  }

  limit(n: number): this {
    this.limitVal = n;
    return this;
  }

  build(): { filters: Partial<T>; limit?: number } {
    return { filters: this.filters, limit: this.limitVal };
  }
}

interface Usuario { id: number; nombre: string; activo: boolean; }

const query = new QueryBuilder<Usuario>()
  .where("activo", true)
  .where("nombre", "Ana")
  .limit(10)
  .build();

38. ¿Qué es `Extract` y `Exclude`?

Utility types para filtrar uniones.

ts
type Todos = "a" | "b" | "c" | "d";

// Extract: los que SÍ están en la segunda unión
type Solo_AB = Extract<Todos, "a" | "b">; // "a" | "b"

// Exclude: los que NO están en la segunda unión
type Sin_AB = Exclude<Todos, "a" | "b">; // "c" | "d"

// Caso real: filtrar tipos de una unión
type SoloCadenas = Extract<string | number | boolean, string>; // string
type SinNull = Exclude<string | null | undefined, null | undefined>; // string

// NonNullable usa Exclude internamente:
type NonNullable<T> = Exclude<T, null | undefined>;

39. ¿Cómo tipar un evento de React correctamente?

ts
import { ChangeEvent, FormEvent, MouseEvent } from "react";

function Formulario() {
  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    console.log(e.target.value);
  };

  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    // ...
  };

  const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
    console.log(e.currentTarget.textContent);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input onChange={handleChange} />
      <button onClick={handleClick}>Enviar</button>
    </form>
  );
}

40. ¿Cómo tipar los props de un componente React con TypeScript?

ts
interface BotonProps {
  label: string;
  variante?: "primario" | "secundario" | "peligro";
  disabled?: boolean;
  onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
  children?: React.ReactNode;
}

function Boton({ label, variante = "primario", disabled, onClick, children }: BotonProps) {
  return (
    <button
      className={`btn btn-${variante}`}
      disabled={disabled}
      onClick={onClick}
    >
      {children ?? label}
    </button>
  );
}

Preguntas trampa y errores comunes

41. ¿Cuál es la diferencia entre `==` y `===` en TypeScript?

En el runtime es igual que en JavaScript: === compara valor y tipo sin coerción. TypeScript agrega que con tipos bien definidos, == suele generar warnings porque mezcla tipos. En código TypeScript bien tipado, siempre usás ===.

42. ¿Por qué `[] as any[]` es distinto de `[] as never[]`?

ts
// any[]: podés pushear cualquier cosa
const a: any[] = [];
a.push(1, "dos", true); // todo bien

// never[]: no podés pushear nada (nunca hay un valor de tipo never)
const n: never[] = [];
n.push(1); // Error: Argument of type 'number' is not assignable to type 'never'

never[] es útil como punto de partida en generics para forzar que el caller especifique el tipo.

43. ¿Cómo evitar el problema de `this` en TypeScript?

ts
class Contador {
  private valor = 0;

  // Mal: si se pasa como callback, pierde el contexto de this
  incrementarMal() {
    this.valor++;
  }

  // Bien: arrow function como propiedad de clase
  incrementar = () => {
    this.valor++;
  };

  // Alternativa: tipear `this` como primer parámetro
  mostrar(this: Contador): string {
    return `Valor: ${this.valor}`;
  }
}

const c = new Contador();
setTimeout(c.incrementar, 100); // ✓ — mantiene el contexto
setTimeout(c.incrementarMal, 100); // ❌ — `this` será undefined

44. ¿Qué es el structural typing y cómo afecta al código?

TypeScript usa tipado estructural (duck typing): dos tipos son compatibles si tienen la misma estructura, sin importar el nombre.

ts
interface Punto { x: number; y: number; }
interface Coordenada { x: number; y: number; }

function dibujar(p: Punto) { /* ... */ }

const c: Coordenada = { x: 1, y: 2 };
dibujar(c); // ✓ — misma estructura, aunque son interfaces distintas

// Esto puede sorprender:
class Empleado { constructor(public nombre: string, public salario: number) {} }
class Robot { constructor(public nombre: string, public salario: number) {} }

const e: Empleado = new Robot("R2D2", 0); // ✓ — misma estructura

45. ¿Cómo debuggear tipos complejos en TypeScript?

ts
// 1. Hover sobre la variable en el IDE (el mejor tool)

// 2. type-fest's Simplify o un helper propio:
type Simplify<T> = { [K in keyof T]: T[K] } & {};

// 3. Asignación deliberada para ver el error:
type MiTipoComplejo = ReturnType<typeof funcionCompleja>;
const prueba: MiTipoComplejo = {} as any;
// El IDE muestra el tipo completo al hovear prueba

// 4. Errores con mensajes custom:
type Assert<T extends true> = T;
type EsString<T> = T extends string ? true : false;
type Test = Assert<EsString<"hola">>; // pasa
type Test2 = Assert<EsString<number>>; // Error en compile time

Consejo final para la entrevista

Las preguntas de TypeScript en entrevistas reales rara vez son teóricas puras. Lo que buscan ver es:

  1. 1Si escribís código que se puede mantener — tipos bien nombrados, generics donde tiene sentido, sin abuso de any
  2. 2Si entendés los trade-offs — cuándo un tipo complejo vale la complejidad y cuándo es over-engineering
  3. 3Si usás el compilador como herramienta — no como obstáculo que hay que bypassear con as any

Cuando no sabés algo en la entrevista, el movimiento correcto es explicar cómo lo buscarías y qué principios aplicarías. TypeScript tiene documentación excelente y los entrevistadores lo saben.

FAQ

¿Cuáles son las preguntas más frecuentes de TypeScript en entrevistas junior?+

Las más frecuentes para junior son: diferencia entre type e interface, qué es any vs unknown, union types, cómo usar generics básicos, qué hace readonly y cómo funcionan los utility types como Partial, Pick y Omit. Con estas bases cobrás confianza para el 80% de las entrevistas.

¿Qué es el tipo unknown y por qué es mejor que any?+

unknown acepta cualquier valor igual que any, pero TypeScript te obliga a verificar el tipo antes de usarlo. Si intentás llamar un método o acceder a una propiedad sin un type check previo, el compilador lanza un error. Esto hace que unknown sea seguro y any sea una trampa silenciosa.

¿Qué son los utility types de TypeScript?+

Son tipos genéricos incluidos en TypeScript que transforman otros tipos. Los más usados: Partial<T> hace todas las props opcionales, Required<T> las hace obligatorias, Pick<T, K> selecciona solo algunas, Omit<T, K> excluye algunas, Readonly<T> las hace inmutables, y Record<K, V> crea un mapa tipado.

¿Cuál es la diferencia entre type e interface en TypeScript?+

Ambas definen la forma de un objeto. Interface soporta extensión con extends y declaración múltiple que se fusiona automáticamente. Type es más flexible: puede definir uniones, intersecciones, tuplas y tipos primitivos. La convención es usar interface para APIs públicas y type para lógica interna compleja.

¿Qué es un discriminated union y para qué se usa?+

Es un patrón donde todos los tipos de una unión tienen una propiedad discriminante con un literal type único. Permite que TypeScript narrowee automáticamente dentro de un switch o if. Es el patrón estándar para modelar estados de UI, resultados de operaciones async y eventos de dominio.

¿Qué hace strictNullChecks en TypeScript?+

Cuando está activo, null y undefined son tipos separados y no se pueden asignar a otras variables sin declararlo explícitamente. Por ejemplo, string no acepta null — tenés que declarar string | null. Esto elimina toda una clase de errores de "cannot read property of null" en runtime.

Related articles

Cómo responder 'háblame de vos' en una entrevista técnica

Descubre cómo abordar la pregunta ‘háblame de vos’ en entrevistas técnicas para roles remotos en tecnología, con ejemplos y consejos útiles.

Cómo preparar una entrevista técnica en inglés siendo de LATAM

Aprende a preparar una entrevista técnica en inglés desde LATAM. Consejos reales para superar los desafíos y destacar en roles remotos en dólares.

Cómo prepararte para una entrevista de Desarrollador Frontend

Descubre consejos prácticos para preparar tu entrevista de Desarrollador Frontend. Domina técnicas, retos y preguntas en roles remotos y en inglés.

Cómo conseguir trabajo remoto de TypeScript en dólares desde LATAM

Descubre cómo aplicar efectivamente a empleos remotos en TypeScript desde LATAM, destacar entre candidatos globales y negociar salarios en dólares.

Prepare for your real interview

Paste your job link: we research who's interviewing you and rehearse you live.

Start free →

Have an interview coming up? Install the live copilot →

InterviewHack.ai

Prepare for the exact interview: who's interviewing you, a tailored CV, and a real coach.

Product

JobsFree ATS checkerInterview-English checkSalary checkLATAM salary reportFree coursesBlogTailored CVSpoken practiceIt's free

Remote jobs

ReactPythonFull-StackLATAMArgentinaMexicoSee all →

Prepare

Spoken practiceFrontendBackendAI EngineerBy companySell with your CV

Company

For employersAboutContactPrivacyTerms

© 2026 InterviewHack.ai · Your CV is yours. Never used to train anything. · A product of IA-PTY