🇺🇸 EN
Angular
·10 min read·↗·🇺🇸 EN

Preguntas esenciales de entrevista en Angular para desarrolladores Junior y Mid-Level

Portada principal del artículo: Preguntas esenciales de entrevista en Angular para desarrolladores Junior y Mid-Level

⚡ ¿Te estás preparando para entrevistas técnicas en Angular moderno? Salta directo a Preguntas de arquitectura y testing moderno (Signals, Vitest, Zoneless) para repasar los temas que más piden los equipos hoy en día.

Durante los últimos años, he entrevistado a decenas de candidatos para puestos de desarrollador Angular. En estas evaluaciones técnicas, noté un patrón muy claro: los desarrolladores que entienden el por qué de los patrones arquitectónicos destacan de inmediato frente a quienes solo memorizan la sintaxis.

Angular ha evolucionado con Standalone Components, el modelo de reactividad con Signals, el nuevo control flow integrado (@if, @for, @let), pruebas unitarias modernas con Vitest y la ejecución experimental Zoneless. Quienes lideran entrevistas técnicas buscan personas que comprendan tanto las bases de código heredadas (legacy) como los paradigmas modernos.

En esta guía reuní las preguntas más frecuentes de entrevista en Angular para roles junior y mid-level, junto con las respuestas esperadas, fragmentos de código y los errores comunes que debes evitar.


Preguntas de entrevista en Angular para Junior 🟢

Las entrevistas para perfiles junior se centran en los bloques fundamentales: el ciclo de vida de los componentes, estado básico y Signals, sintaxis de plantillas, inyección de dependencias y formularios.

1. ¿Qué son los Standalone Components y por qué son el estándar en el Angular moderno?

  • Respuesta esperada: Los Standalone Components eliminan la necesidad de usar NgModule. Al configurar standalone: true (que ya viene por defecto), el componente importa sus dependencias (otros componentes, directivas o pipes) directamente dentro de su decorador @Component({ imports: [...] }). Esto mejora el tree-shaking, simplifica la estructura del proyecto y facilita reutilizar componentes.
  • Error común: Olvidar que ya no necesitas importar CommonModule cuando usas el nuevo control flow integrado (@if, @for).

2. ¿Cómo funcionan las Signals en Angular y en qué se diferencian de las propiedades normales?

  • Respuesta esperada: Un signal() es un contenedor reactivo alrededor de un valor que notifica a los consumidores cuando ese valor cambia. Las Signals ofrecen reactividad granular:
    import { Component, signal, computed } from '@angular/core';
     
    @Component({
      selector: 'app-counter',
      template: `
        <p>Count: {{ count() }}</p>
        <p>Double: {{ doubleCount() }}</p>
        <button (click)="increment()">Increment</button>
      `
    })
    export class CounterComponent {
      count = signal(0);
      doubleCount = computed(() => this.count() * 2);
     
      increment() {
        this.count.update(val => val + 1);
      }
    }
  • Error común: Llamar a las signals sin paréntesis en las plantillas ({{ count }} en lugar de {{ count() }}) o mutar objetos complejos directamente dentro de set() sin crear una nueva referencia.

3. ¿Qué es el Control Flow integrado (@if, @for, @let, @switch)?

  • Respuesta esperada: Angular reemplazó el control flow basado en directivas (*ngIf, *ngFor, *ngSwitch) por una sintaxis de bloques integrada:
    @let currentUser = user();
     
    @if (currentUser) {
      <p>Welcome, {{ currentUser.name }}</p>
    } @else {
      <p>Please log in</p>
    }
     
    <ul>
      @for (item of items(); track item.id) {
        <li>{{ item.name }}</li>
      } @empty {
        <li>No items available.</li>
      }
    </ul>
    La expresión track es obligatoria en @for, lo que optimiza el renderizado del DOM sin necesidad de crear una función trackBy separada.
  • Error común: Olvidar la expresión obligatoria track dentro de los bloques @for.

4. ¿Cuál es la diferencia entre ngOnInit, constructor y ngOnDestroy?

  • Respuesta esperada:
    • constructor: Es un método estándar de TypeScript que se debe usar solo para inicializaciones ligeras (por ejemplo, asignar dependencias inyectadas mediante inject()). Aquí nunca debes colocar lógica pesada ni peticiones HTTP.
    • ngOnInit: Es un hook del ciclo de vida de Angular que se ejecuta una vez que los inputs del componente están listos. Es el lugar ideal para inicializar el estado, pedir datos iniciales o suscribirse a flujos.
    • ngOnDestroy: Se ejecuta justo antes de que Angular destruya el componente. Se usa para tareas de limpieza, como cancelar suscripciones manuales de RxJS, limpiar timers o desconectar listeners de eventos.
  • Error común: Hacer peticiones HTTP dentro del constructor antes de que los inputs del componente y la vista estén inicializados.

5. ¿Cuáles son las diferencias entre Reactive Forms y Template-Driven Forms?

  • Respuesta esperada:
    • Reactive Forms: Son programáticos y sincrónicos. Los controles (FormControl, FormGroup, FormArray) se definen en la clase de TypeScript. Cuentan con tipado estricto, son fáciles de probar con tests unitarios y resultan ideales para validaciones dinámicas y complejas.
    • Template-Driven Forms: Se basan en directivas en la plantilla (ngModel, ngForm). Son asincrónicos y prácticos para formularios simples con enlace bidireccional, pero son más difíciles de probar de forma unitaria sin renderizar el DOM.
  • Error común: Confundir el tipado estricto en Reactive Forms o intentar modificar los valores del formulario directamente sin usar .setValue() o .patchValue().

6. ¿Qué es la Inyección de Dependencias y cómo se usa la función inject()?

  • Respuesta esperada: La Inyección de Dependencias (DI) es un patrón de diseño donde una clase recibe sus dependencias desde un inyector externo en vez de crearlas por sí misma. El Angular moderno usa la función inject() en inicializadores en lugar de la inyección por constructor:
    @Component({ ... })
    export class UserComponent {
      private http = inject(HttpClient);
      private authService = inject(AuthService);
    }
    Esto hace que la herencia, las utilidades componibles y los guards funcionales sean mucho más limpios.
  • Error común: Llamar a inject() dentro de callbacks asincrónicos o hooks del ciclo de vida donde el contexto de inyección ya no está activo.

Preguntas de entrevista en Angular para Mid-Level 🟡

Las preguntas para perfiles mid-level evalúan tu comprensión de la arquitectura asincrónica, optimización de rendimiento, pruebas unitarias con Vitest, estrategias con operadores de RxJS y la ejecución moderna Zoneless.

1. ¿Cuándo deberías usar Signals frente a Observables de RxJS?

  • Respuesta esperada:
    • Signals: Ideales para manejo de estado sincrónico, reactividad de la interfaz, estado derivado (computed()) y renderizado en plantillas.
    • RxJS: Indispensable para operaciones asincrónicas complejas, manejo de eventos en el tiempo, debouncing, web sockets, polling y lógica de reintentos.
    • Interoperabilidad: Angular ofrece @angular/core/rxjs-interop con toSignal() y toObservable() para conectar ambos mundos con facilidad.
  • Error común: Creer que las Signals reemplazan por completo a RxJS. Los Observables siguen siendo el estándar para flujos de eventos asincrónicos y llamadas HTTP.

2. ¿Cómo ha evolucionado el testing unitario en Angular (Karma/Jasmine frente a Vitest)?

  • Respuesta esperada: Históricamente, Angular usaba Karma y Jasmine, herramientas que dependían de iniciar una instancia real del navegador y tenían tiempos de arranque lentos. En el Angular moderno, Vitest tiene soporte nativo a través del builder de pruebas de @angular/build. Vitest ejecuta las pruebas directamente en Node.js usando ESM, completando suites enteras en milisegundos con utilidades integradas de mocking (vi.fn(), vi.spyOn()) y manteniendo las APIs de TestBed.
  • Error común: Seguir usando el módulo obsoleto HttpClientTestingModule en lugar de la función moderna provideHttpClientTesting().

3. ¿Qué es Zoneless Angular y cómo funciona?

  • Respuesta esperada: Tradicionalmente, Angular dependía de zone.js para interceptar APIs asincrónicas del navegador (eventos del DOM, temporizadores, promesas) y disparar la detección de cambios de arriba hacia abajo. Zoneless Angular (provideExperimentalZonelessChangeDetection()) elimina zone.js, apoyándose en Signals y notificaciones directas del framework para actualizar la vista de forma quirúrgica. Esto reduce el tamaño del bundle en unos 15 kB y mejora el rendimiento en tiempo de ejecución.
  • Error común: Creer que Zoneless obliga a reescribir todos los componentes, cuando en realidad los componentes basados en Signals funcionan de forma natural sin Zone.js.

4. Explica la diferencia entre switchMap, mergeMap, concatMap y exhaustMap.

  • Respuesta esperada:
    • switchMap: Cancela el observable interno anterior cuando llega un nuevo valor. Caso de uso: Búsquedas en tiempo real (descarta peticiones obsoletas).
    • mergeMap: Ejecuta todos los observables internos de forma concurrente sin cancelar ni esperar. Caso de uso: Descargas en paralelo o subida de varios archivos al mismo tiempo.
    • concatMap: Encola los observables internos en secuencia, ejecutando uno tras otro en orden estricto. Caso de uso: Secuencia de transacciones bancarias u operaciones de guardado ordenadas.
    • exhaustMap: Ignora nuevos valores mientras el observable interno actual se esté ejecutando. Caso de uso: Botones de envío en formularios (evita dobles clics o envíos duplicados).
  • Error común: Usar mergeMap en campos de búsqueda, lo que genera condiciones de carrera (race conditions) donde respuestas viejas pueden sobrescribir resultados más nuevos.

5. ¿Cómo funciona la detección de cambios con OnPush frente a Default?

  • Respuesta esperada:
    • Default (ChangeDetectionStrategy.Default): Angular ejecuta la detección de cambios en todo el árbol de componentes ante cualquier evento del navegador.
    • OnPush: Angular revisa el componente únicamente cuando:
      1. Cambia la referencia de un @Input() o de un signal input().
      2. Se dispara un manejador de eventos dentro del componente o de sus hijos.
      3. Un pipe async emite un nuevo valor o una Signal leída en la plantilla se actualiza.
      4. Se solicita la detección de cambios manualmente mediante ChangeDetectorRef.markForCheck().
  • Error común: Mutar un arreglo u objeto directamente (por ejemplo, items.push(newItem)) y esperar que un componente con OnPush se actualice sin generar una nueva referencia (items = [...items, newItem]).

6. ¿Qué son las Deferrable Views (@defer) y cómo optimizan el rendimiento?

  • Respuesta esperada: @defer permite cargar de forma diferida (lazy loading) y declarativa secciones de la plantilla y dependencias pesadas:
    @defer (on viewport) {
      <heavy-chart-widget [data]="chartData()" />
    } @placeholder {
      <div class="skeleton-loader">Loading chart...</div>
    } @loading (minimum 500ms) {
      <spinner />
    } @error {
      <p>Failed to load chart.</p>
    }
    Angular divide los componentes diferidos en fragmentos (chunks) de JavaScript independientes que solo se descargan cuando se cumple la condición del disparador.
  • Error común: No incluir bloques de respaldo como @placeholder o @loading para cuidar la experiencia del usuario.

Errores clave en entrevistas y cómo evitarlos 💡

ÁreaError comúnEnfoque senior recomendado
ReactividadTratar a Signals y RxJS como enemigosUsa Signals para el estado sincrónico de la interfaz y RxJS para flujos de eventos asincrónicos.
TestingPruebas lentas ejecutadas en KarmaUsa Vitest y provideHttpClientTesting() para pruebas rápidas con ESM.
RendimientoDejar todos los componentes con detección de cambios en DefaultUsa ChangeDetectionStrategy.OnPush por defecto y aplica @defer para contenido que queda fuera del primer pantallazo.
Inyección de DependenciasAbusar de parámetros complejos en el constructorUsa inject() para crear utilidades funcionales y componibles.
ArquitecturaComponentes gigantes con demasiadas responsabilidadesSepara en componentes contenedores (smart) y de presentación (dumb) apoyándote en Signals.

Resumen

Prepararte para una entrevista técnica de Angular consiste en entender las decisiones de arquitectura que dan vida al framework:

  1. Signals ofrecen un manejo de estado declarativo y granular para la interfaz.
  2. Standalone Components y el Control Flow integrado permiten crear plantillas limpias y fáciles de mantener sin la complejidad de NgModule.
  3. Vitest aporta pruebas unitarias rápidas y confiables.
  4. Operadores de RxJS (switchMap, exhaustMap) siguen siendo la herramienta adecuada para flujos asincrónicos.
  5. OnPush y @defer ofrecen un rendimiento sólido para aplicaciones empresariales.
Parte de la serie Angular

These are my experiences learning and facing my daily challenges working with Angular.

Ver serie completa

Preguntas Frecuentes

¿Cuáles son las preguntas de entrevista más comunes sobre Angular para perfiles junior en 2026?

Las entrevistas junior se enfocan en conceptos fundamentales: ciclo de vida de componentes, Signals frente a estado primitivo, nuevo control flow en plantillas (@if, @for con track), formularios reactivos tipados y la función inject().

¿Cuál es la diferencia entre Angular Signals y RxJS Observables en una entrevista?

Signals representan estado sincrónico y libre de inconsistencias (glitch-free) con reactividad granular y seguimiento de valores (get/set). Los Observables representan flujos de eventos asincrónicos en el tiempo con operadores de transformación (debouncing, cancelación, combinación).

¿Cómo se hacen las pruebas unitarias en Angular moderno en comparación con versiones anteriores?

Angular moderno pasó de Karma y Jasmine a Vitest y ESM nativo con TestBed, usando vi.fn() y provideHttpClientTesting() para ejecutar pruebas muy rápido sin la sobrecarga de un navegador real.

¿Qué es Zoneless Angular y cómo cambia la detección de cambios?

Zoneless Angular elimina la necesidad de zone.js y sus modificaciones a las APIs del navegador, apoyándose en Signals y notificaciones directas al planificador (provideExperimentalZonelessChangeDetection()) para mejorar el rendimiento y reducir el tamaño del bundle.

Artículos Relacionados

Compartir este artículo

Si esta guía te resultó útil, compártela con tu equipo o con otros desarrolladores.


Software real. Lecciones reales.

Comparto las lecciones que aprendí por las malas, para que puedas evitarlas o estar preparado cuando ocurran.

User avatar
User avatar
User avatar
User avatar
+13K

Únete a 13,800+ desarrolladores y lectores.

Cero spam. Cancela tu suscripción en cualquier momento.