Skip to content

Support generic SimpleChange<T> for use in ngOnChanges #17560

@matt-senseye

Description

@matt-senseye

I'm submitting a ...


[ ] Regression (behavior that used to work and stopped working in a new release)
[ ] Bug report 
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Please tell us about your environment


Angular version: 4.2.2

Current behavior

The ngOnChanges lifecycle hook method provides changes: SimpleChanges. Within that, each property is of type SimpleChange which provides currentValue:any and previousValue:any.

Because SimpleChange uses type any and does not use generics, there is no type safety (or autocomplete etc.) and we lose the benefits of TypeScript when working on code that operates inside ngOnChanges.

Expected behavior

Adding generics, SimpleChange<T = any> would offer developers the chance to define the types of their inputs, whilst falling back to the current behaviour of any otherwise.

Example 1: Standard behaviour available now

import { Component, Input, OnChanges, SimpleChanges, SimpleChange } from '@angular/core';

@Component({
  // ...
})
export class ExampleComponent implements OnChanges {
  @Input() foo: string;
  @Input() bar: number;

  ngOnChanges(changes: SimpleChanges): void {
    // BAD: We get no autocomplete for the properties on changes
    // BAD: We are not able to access changes.foo.currentValue here with dot syntax, we have to use changes["foo"].currentValue
    // BAD: Editor is not aware of type of changes["foo"].currentValue, so we get no further type checking / autocompletion
  }
}

Example 2: Slight improvement by adding own extension of SimpleChanges

import { Component, Input, OnChanges, SimpleChanges, SimpleChange } from '@angular/core';

interface IExampleComponentChanges extends SimpleChanges {
  foo: SimpleChange;
  bar: SimpleChange;
}

@Component({
  // ...
})
export class ExampleComponent implements OnChanges {
  @Input() foo: string;
  @Input() bar: number;

  ngOnChanges(changes: IExampleComponentChanges): void {
    // GOOD: Editor is aware of which properties are available in changes
    // GOOD: We are able to access changes.foo.currentValue here with dot syntax
    // BAD: Editor is not aware of type of changes.foo.currentValue, so we get no further type checking / autocompletion
  }
}

Example 3: If SimpleChange supported generics...

import { Component, Input, OnChanges, SimpleChanges, SimpleChange } from '@angular/core';

interface IExampleComponentChanges extends SimpleChanges {
  foo: SimpleChange<string>;
  bar: SimpleChange<number>;
}

@Component({
  // ...
})
export class ExampleComponent implements OnChanges {
  @Input() foo: string;
  @Input() bar: number;

  ngOnChanges(changes: IExampleComponentChanges): void {
    // GOOD: Editor is aware of which properties are available in changes
    // GOOD: We are able to access changes.foo.currentValue here with dot syntax
    // GOOD: Editor is aware of the type of changes.foo.currentValue so we get full type safety and autocompletion all the way down
  }
}

Workaround

In my project I have found a way to achieve this by adding my own definition and using that in place of SimpleChange. It would be great if this were possible as part of the framework though and thought it might be helpful to share.

declare class SimpleChangeGeneric<T = any> extends SimpleChange {
  previousValue: T;
  currentValue: T;
  firstChange: boolean;
  constructor(previousValue: T, currentValue: T, firstChange: boolean);
  /**
   * Check whether the new value is the first value assigned.
   */
  isFirstChange(): boolean;
}

// ...
export interface IExampleComponentChanges extends SimpleChanges {
  foo: SimpleChangeGeneric<string>;
}
// ...

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions