Repository: angular
Issue: Support generic SimpleChange<T> for use in ngOnChanges
Labels: feature,area: core,core: lifecycle hooks,core: change detection,cross-cutting: types,feature: under consideration

## I'm submitting a ...
<!-- Check one of the following options with "x" -->
<pre><code>
[ ] Regression (behavior that used to work and stopped working in a new release)
[ ] Bug report <!-- Please search github for a similar issue or PR before submitting -->
[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
</code></pre>

## Please tell us about your environment

<pre><code>
Angular version: 4.2.2
</pre></code>

## 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>;
}
// ...
```