DEV Community

Amos Isaila
Amos Isaila

Posted on • Originally published at codigotipado.com on

Angular 19: Enhanced Signal Debugging Features

Angular 19 introduces significant improvements to signal debugging capabilities. These improvements are primarily focused on enhancing the Angular DevTools experience.

Debug Names for Signals

All signal-related APIs now support a debugName option that helps identify signals in debugging tools:

// Signal
const counter = signal(0, { debugName: 'counterSignal' });

// Computed
const doubled = computed(() => counter() * 2, { debugName: 'doubledSignal' });

// Effect
effect(() => console.log(counter()), { debugName: 'loggingEffect' });

// Input
@Component({...})
class MyComponent {
  count = input(0, { debugName: 'countInput' });
}

// Model
@Component({...})
class MyComponent {
  value = model(0, { debugName: 'valueModel' });
}

// Queries
@Component({...})
class MyComponent {
  child = viewChild('childRef', { debugName: 'childQuery' });
  children = viewChildren('itemRef', { debugName: 'itemsQuery' });
}
Enter fullscreen mode Exit fullscreen mode

Signal Graph API

A new debug API getSignalGraph has been introduced that provides visibility into the signal dependency graph:

interface DebugSignalGraphNode {
  kind: string; // 'signal' | 'computed' | 'effect' | 'template' | 'unknown'
  label: string; // The debugName or identifier
  value?: unknown; // Current value (for signals and computed)
}

interface DebugSignalGraphEdge {
  consumer: number; // Index of the consuming node
  producer: number; // Index of the producing node
}

interface DebugSignalGraph {
  nodes: DebugSignalGraphNode[];
  edges: DebugSignalGraphEdge[];
}
Enter fullscreen mode Exit fullscreen mode

Example usage:

@Component({
  selector: 'my-component',
  template: `<div>{{ computedValue() }}</div>`
})
class MyComponent {
  private count = signal(0, { debugName: 'count' });
  computedValue = computed(() => this.count() * 2, { debugName: 'doubledCount' });

  constructor() {
    // Get the signal graph for this component
    const graph = getSignalGraph(this.injector);
    // Returns nodes and edges representing the signal relationships
  }
}
Enter fullscreen mode Exit fullscreen mode

Type Identification for Signal Nodes

Angular 19 introduces a new kind property to the signal prototype nodes, making it easier to identify different types of signals in debugging scenarios. This enhancement complements the existing debugging features by providing built-in type information for each signal node.

interface ReactiveNode {
  // ... existing properties
  kind: string; // Identifies the type of signal node
}
Enter fullscreen mode Exit fullscreen mode

The kind property can have various values including:

  • 'signal' - For basic signals
  • 'computed' - For computed signals
  • 'effect' - For effect signals
  • 'input' - For input signals
  • 'unknown' - Default value for base reactive nodes

Example usage with different signal types:

@Component({
  selector: 'debug-component'
})
class DebugComponent {
  // Basic signal shows 'signal' kind
  counter = signal(0);

  // Computed signal shows 'computed' kind
  doubled = computed(() => this.counter() * 2);

  // Effect shows 'effect' kind
  counterEffect = effect(() => {
    console.log('Counter:', this.counter());
  });

  constructor() {
    // Using getSignalGraph to inspect node kinds
    const graph = getSignalGraph(this.injector);
    console.log(graph.nodes.map(node => node.kind));
  }
}
Enter fullscreen mode Exit fullscreen mode

Integration with Debug Tools The kind property enhances debugging capabilities by:

  1. Enabling precise filtering and grouping of signals by their type
  2. Improving signal graph visualization with type-specific representations
  3. Supporting better DevTools integration with type-aware debugging features

The design decision to use a string type instead of a strict union type ('signal' | 'computed' | 'effect') allows for future extensibility, enabling Angular and third-party libraries to define custom signal types without modifying the core type definitions.

When combined with the debugName option and Signal Graph API, the kind property provides a comprehensive debugging experience:

@Component({
  selector: 'advanced-debug'
})
class AdvancedDebugComponent {
  private count = signal(0, { debugName: 'counter' });
  doubled = computed(() => this.count() * 2, { debugName: 'doubledCounter' });

  constructor() {
    const graph = getSignalGraph(this.injector);

    // Now we can identify both the name and type of each signal
    graph.nodes.forEach(node => {
      console.log(`${node.debugName}: ${node.kind}`);
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Future Enhancements

  1. Automatic Debug Names : A TypeScript transform is being developed that will automatically add debug names to signals based on their usage context, eliminating the need for manual debug name specification.
  2. Enhanced DevTools Integration : The Angular DevTools will leverage these new debugging features to provide:
  • Real-time signal value inspection
  • Signal relationship visualization
  • Performance monitoring for signal computations

3. Signal Graph Visualization : The DevTools will be able to create visual representations of signal relationships, making it easier to understand how data flows through your application.

Developer Benefits

  1. Improved Debugging Experience :
  • Clear identification of signals in debugging tools
  • Better understanding of signal relationships
  • Easier tracking of signal value changes
  1. Better Performance Analysis :
  • Ability to identify unnecessary signal computations
  • Understanding of signal dependency chains
  • Detection of potential optimization opportunities
  1. Enhanced Development Workflow :
  • Quick identification of signal-related issues
  • Better understanding of reactive data flow
  • Simplified debugging of complex signal interactions

Implementation Notes

The signal debugging features are built on top of a new internal profiler system that tracks signal creation and relationships. This system is designed to have minimal performance impact in production builds while providing rich debugging information during development.

PRs you must follow

  • feat(core): introduce debugName optional arg to framework signal functions (#57073)
  • feat(core): implement getSignalGraph debug API (#57074)
  • feat(core): add “kind” to signal prototype nodes (#58333)

Thanks for reading so far 🙏

I’d like to have your feedback so please leave a comment , clap or follow. 👏

Spread the Angular love! 💜

If you really liked it, share it among your community, tech bros and whoever you want! 🚀👥

Don’t forget to follow me and stay updated: 📱

Thanks for being part of this Angular journey! 👋😁

Originally published at https://www.codigotipado.com.

Top comments (0)