Menu

Preguntas de entrevista de TypeScript (25 con código)

25 preguntas de entrevista de TypeScript con respuestas cortas, correctas y con código, ordenadas de principiante a avanzado: any frente a unknown, interface frente a type, genéricos, estrechamiento, utility types, mapped y conditional types, tipado estructural, tsconfig y TypeScript 7.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Estas son las preguntas de TypeScript que más hacen los entrevistadores, con la respuesta corta que deberías saber dar y un ejemplo pequeño. Están agrupadas por nivel; un puesto junior suele quedarse en el primer grupo, y uno senior espera que escribas de memoria los tipos del último.

Preguntas de nivel principiante

1. ¿Qué es TypeScript?

TypeScript es JavaScript con tipos estáticos, creado por Microsoft. Anotas los valores con tipos, el compilador los comprueba y después elimina los tipos y genera JavaScript normal que funciona en cualquier sitio donde funcione JavaScript.

Sin el comentario @ts-expect-error, la segunda llamada es un error de compilación, así que el bug nunca llega a producción.

2. ¿TypeScript comprueba los tipos en tiempo de ejecución?

No. Los tipos se borran durante la compilación; en la salida no queda rastro de ellos. La ejecución de arriba imprime 23 porque en tiempo de ejecución nada sabe que a debería ser un número. Para comprobar datos que vienen de fuera del programa (JSON, entrada del usuario, respuestas de una API) escribes comprobaciones reales, como un type guard o un validador de esquemas.

3. ¿Cuáles son los tipos básicos?

string, number (un único tipo para enteros y decimales; no existe int), boolean, bigint, symbol, null y undefined, más los arrays (number[]), las tuplas ([string, number]), los tipos objeto, any, unknown, never y void. Usa los nombres en minúscula: String y Number son los tipos de los objetos envoltorio.

4. ¿Qué diferencia hay entre any y unknown?

Los dos aceptan cualquier valor. any además desactiva la comprobación, así que cualquier operación compila. unknown no permite nada hasta que lo estrechas, lo que lo convierte en el tipo seguro para valores que todavía no has comprobado.

5. ¿Qué es la inferencia de tipos?

El compilador deduce tipos que no escribiste: let count = 0 es un number, const mode = "dark" es el tipo literal "dark", y el tipo de retorno de una función sale de sus sentencias return. La regla habitual es anotar los parámetros de las funciones y los tipos de retorno públicos y dejar que la inferencia se ocupe de las variables locales.

6. ¿Qué diferencia hay entre interface y type?

Los dos describen formas de objeto, y una clase puede hacer implements de cualquiera de ellos. Una interface se puede reabrir y fusionar (declaration merging) y hace extends de otras interfaces. Un alias type puede nombrar cualquier cosa: uniones, tuplas, primitivos, mapped types y conditional types.

interface User { name: string }
interface User { age: number }       // merged: User has name and age

type Id = string | number;           // only a type alias can be a union
type Pair = [string, number];        // or a tuple
type Admin = User & { role: "admin" };

Una convención habitual es interface para formas de objeto y type para todo lo demás. La comparación completa está en la página de interface frente a type.

7. ¿Qué son los tipos unión e intersección?

Una unión A | B es un valor que es uno de los tipos; solo puedes usar los miembros comunes a todos hasta que lo estreches. Una intersección A & B es un valor que es ambos a la vez, con todos los miembros de cada uno.

type Id = string | number;                 // either
type Timestamped = { createdAt: Date };
type Post = { title: string } & Timestamped; // both: title and createdAt

8. ¿Qué diferencia hay entre void y never?

void es el tipo de retorno de una función que termina con normalidad sin devolver un valor útil. never es el tipo de algo que no puede ocurrir: una función que siempre lanza o que no termina nunca, o una unión a la que se le han quitado todos los casos. never se puede asignar a cualquier tipo, y ningún valor se puede asignar a never.

function log(msg: string): void { console.log(msg); }
function fail(msg: string): never { throw new Error(msg); }
type Impossible = string & number; // never

Preguntas de nivel intermedio

9. ¿Qué es el estrechamiento de tipos?

El estrechamiento (narrowing) es el compilador siguiendo tus comprobaciones y refinando un tipo dentro de cada rama. Entiende typeof, instanceof, in, las comprobaciones de igualdad, la veracidad y los type guards definidos por el usuario.

10. ¿Qué es un type guard definido por el usuario?

Una función cuyo tipo de retorno es value is T. Cuando devuelve true, la variable de quien llama se estrecha a T. El compilador se fía de la función, así que su cuerpo tiene que comprobar el valor de verdad.

interface Cat { meow(): void }

function isCat(value: unknown): value is Cat {
    return (
        typeof value === "object" &&
        value !== null &&
        "meow" in value &&
        typeof value.meow === "function"
    );
}

Una función de aserción, function assertCat(v: unknown): asserts v is Cat, estrecha lanzando un error en lugar de devolver false.

11. ¿Qué son los genéricos?

Parámetros de tipo que permiten que una función, clase o tipo funcione con muchos tipos manteniendo la relación entre la entrada y la salida. T se infiere a partir de los argumentos, y extends restringe lo que puede ser.

pluck(users, "email") sería un error de compilación, porque "email" no es un keyof del tipo usuario.

12. ¿Qué hacen keyof y typeof en un tipo?

keyof T es la unión de los nombres de propiedad de T. En una posición de tipo, typeof x da el tipo de una variable. Juntos, keyof typeof obj convierte las claves de un objeto en una unión.

const colors = { red: "#f00", green: "#0f0" };
type Colors = typeof colors;        // { red: string; green: string }
type ColorName = keyof typeof colors; // "red" | "green"

13. ¿Qué son los utility types? Nombra algunos.

Tipos genéricos integrados que transforman otros tipos. Los más preguntados:

UtilityResultado
Partial<T>todas las propiedades opcionales
Required<T>todas las propiedades obligatorias
Readonly<T>todas las propiedades readonly
Pick<T, "a" | "b">solo las propiedades indicadas
Omit<T, "a">todas las propiedades excepto las indicadas
Record<K, V>un objeto con claves K y valores V
Exclude<U, X>, Extract<U, X>quitar o conservar miembros de una unión
NonNullable<T>T sin null ni undefined
ReturnType<F>, Parameters<F>el tipo de retorno o los tipos de los parámetros de una función
Awaited<T>el valor en que se resuelve una promesa

La lista completa está en la página de utility types.

14. ¿Qué es una unión discriminada?

Una unión de tipos objeto que comparten una propiedad «etiqueta» literal. Comprobar la etiqueta estrecha el valor a un miembro, y una comprobación con never en la rama default hace que el compilador informe de cualquier caso que olvides.

15. ¿Qué diferencia hay entre as y satisfies?

value as T es una aserción de tipo: le dice al compilador que trate el valor como T y se salta casi todas las comprobaciones. value satisfies T comprueba el valor contra T pero conserva el tipo propio del valor, más preciso.

type Theme = { primary: string; secondary: string };

const a = { primary: "#07f" } as Theme;        // compiles: the missing key is not reported
const b = { primary: "#07f" } satisfies Theme; // error TS2741: Property 'secondary' is missing
const c = {} as { name: string };              // compiles; c.name is undefined at run time

Cuando el objeto está completo, satisfies también conserva su propio tipo inferido: comprobada contra Record<string, string>, la variable sigue sabiendo exactamente qué claves tiene, mientras que una anotación la ensancharía a cualquier clave string.

16. ¿Qué hace el operador ! detrás de una variable?

Es la aserción non-null: el! quita null y undefined del tipo. No genera ninguna comprobación, así que si el valor es realmente null, el programa falla donde se usa. Es preferible ?., ?? o un if explícito.

17. ¿Qué diferencia hay entre private y #private?

private solo lo hace cumplir el compilador; la propiedad es una propiedad normal en la salida en JavaScript. #field es un campo privado de JavaScript que hace cumplir el propio runtime.

protected funciona como private pero también permite el acceso desde subclases, y readonly prohíbe reasignar después de la construcción.

18. ¿Qué diferencia hay entre una clase abstracta y una interfaz?

Una interfaz es solo un tipo: describe una forma y desaparece de la salida. Una clase abstracta es una clase real que no se puede instanciar; puede tener métodos implementados, campos y constructores junto a miembros abstract que las subclases deben implementar. Una clase puede implementar muchas interfaces pero solo extender una clase.

abstract class Repository<T> {
    protected items: T[] = [];
    abstract validate(item: T): boolean; // subclasses must implement
    add(item: T): void {                 // shared implementation
        if (this.validate(item)) this.items.push(item);
    }
}

19. ¿Qué es la sobrecarga de funciones en TypeScript?

Varias firmas de llamada seguidas de una única implementación cuya firma es compatible con todas ellas. Quien llama solo ve las sobrecargas, así que cada llamada obtiene un tipo de retorno preciso.

function parse(value: string): number;
function parse(value: string[]): number[];
function parse(value: string | string[]): number | number[] {
    return Array.isArray(value) ? value.map(Number) : Number(value);
}

const one = parse("4");          // number
const many = parse(["1", "2"]);  // number[]

Cuando el tipo de retorno no depende del tipo del argumento, una sola firma con un parámetro unión es más sencilla.

Preguntas de nivel avanzado

20. ¿Qué es el tipado estructural?

TypeScript compara los tipos por su forma, no por su nombre. Se acepta cualquier valor que tenga las propiedades requeridas, aunque nunca se haya declarado con ese tipo.

El color de más no es problema aquí porque pixel es una variable. Pasar el objeto literal directamente, show({ x: 3, y: 4, color: "red" }), es un error de propiedad de más, una comprobación que solo se aplica a literales recién creados. Cuando dos tipos con la misma forma no deben mezclarse (un UserId y un OrderId que son ambos strings), usa un branded type: type UserId = string & { readonly __brand: "UserId" }.

21. ¿Cómo implementarías Readonly y Partial tú mismo?

Con mapped types: recorre keyof T y añade un modificador a cada propiedad.

type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
type MyPartial<T> = { [K in keyof T]?: T[K] };
type Mutable<T> = { -readonly [K in keyof T]: T[K] }; // "-" removes a modifier

type User = { name: string; age: number };
type Draft = MyPartial<User>; // { name?: string; age?: number }

22. ¿Qué son los conditional types e infer?

T extends U ? X : Y elige un tipo según una condición. Dentro de la condición, infer declara una variable de tipo que captura una parte del tipo que coincide. Los conditional types se distribuyen sobre las uniones.

type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never;
type ElementOf<T> = T extends (infer E)[] ? E : T;

type A = MyReturnType<() => Promise<number>>; // Promise<number>
type B = ElementOf<string[]>;                 // string
type C = ElementOf<number | boolean[]>;       // number | boolean (distributed)

Hay más patrones en la página de conditional types.

23. ¿Qué es un archivo .d.ts y qué hace declare?

Un archivo de declaraciones contiene solo tipos para código que existe en otro sitio, como una librería de JavaScript o las APIs del navegador. declare indica que un valor existe sin crearlo: declare const VERSION: string; no compila a nada. Los tipos de las librerías vienen incluidos en el paquete o en paquetes @types/{name}, y tsc genera archivos .d.ts para tu propio código con declaration: true.

24. ¿Qué hace strict y qué opciones de tsconfig importan más?

"strict": true activa noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables y strictBuiltinIteratorReturn. En TypeScript 7 está activado por defecto. Las otras opciones por las que preguntan los entrevistadores:

OpciónRespuesta en una línea
targetqué versión de JavaScript usa la salida
moduleel formato de módulos de salida: nodenext sigue las reglas de Node, esnext/preserve mantienen import para un bundler
moduleResolutioncómo se encuentran los imports: nodenext pide ./file.js en archivos ES module, bundler acepta ./file
noUncheckedIndexedAccessarr[i] incluye undefined en su tipo
pathsalias de import solo para el comprobador de tipos; la salida mantiene el alias, así que un bundler o el campo imports de Node tiene que resolverlo
skipLibCheckno comprobar los archivos .d.ts, por velocidad
verbatimModuleSyntaxlos imports que solo se usan como tipos deben marcarse con type; los demás imports se mantienen tal cual

25. ¿Qué es TypeScript 7?

El compilador de TypeScript reescrito en Go como programa nativo, publicado como la versión 7 del paquete npm typescript. El comando sigue siendo tsc y el lenguaje es el mismo, pero es mucho más rápido que el compilador 6.x basado en JavaScript: el equipo de TypeScript informa de mejoras de 8x a 12x en compilaciones completas típicas, gracias al código nativo y al multihilo con memoria compartida. También aplica eliminaciones que la 6.0 había marcado como obsoletas; por ejemplo, baseUrl, outFile, moduleResolution: "node10", module: "amd" y alwaysStrict: false son ahora errores (TS5102, TS5108) que te piden quitarlos.

Preguntas frecuentes

¿Cuáles son las preguntas de entrevista de TypeScript más habituales?

Las que más salen: la diferencia entre any y unknown, interface frente a type, cómo funcionan los genéricos, cómo funcionan el estrechamiento y los type guards, qué hacen utility types como Partial, Pick y Omit, y si TypeScript comprueba los tipos en tiempo de ejecución (no lo hace).

¿Qué preguntas de TypeScript se hacen a desarrolladores senior?

Espera tener que escribir tipos, no solo leerlos: implementar Readonly o ReturnType con mapped y conditional types, explicar el tipado estructural y cuándo usar branded types, diseñar una unión discriminada con comprobación exhaustiva y comentar opciones de tsconfig como strict, noUncheckedIndexedAccess y la resolución de módulos.

¿Cómo me preparo para una entrevista de TypeScript?

Escribe programas pequeños con strict activado y lee los errores del compilador hasta que puedas predecirlos. Debes poder explicar el estrechamiento, los genéricos con restricciones, los utility types principales y por qué las aserciones de tipo son inseguras, cada cosa con un ejemplo de dos líneas.

¿Se pregunta TypeScript en entrevistas de React y Angular?

Normalmente sí. Angular está escrito en TypeScript y sus aplicaciones también, así que las entrevistas de Angular suelen darlo por hecho, decoradores como @Component y modificadores de acceso incluidos. Las entrevistas de React para un código TypeScript suelen pedirte tipar props, estado y manejadores de eventos, lo que usa las mismas interfaces, uniones y genéricos que se ven aquí.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR