Search code examples
angulartypescriptangular10

Angular NameOf in Component for String Safe and NgOnchanges


What is the best way to compare NgOnChanges, while making it String Type safe in Angular? Currently this is what I am doing.

NgOnChanges SimpleChanges variable is datatype : any and accepts any variable name, even if misspelled. Trying to find clean way to prevent this.

Original:

else if (changes?.product?.previousValue != changes?.product?.currentValue) {
    this.submitSearch();

New:

export const nameof = <T>(name: keyof T) => name;

public readonly productMember = nameof<WebStoreSearchComponent>("product");

if ((changes[this.productMember]?.previousValue != changes[this.productMember]?.currentValue) {
    this.submitSearch();

Does Angular have any native way to conduct this?

Resources:

https://schneidenbach.gitbooks.io/typescript-cookbook/content/nameof-operator.html

Note: Getters/setters are not a solution, since specifically asking about string safe for ngonchanges.


Solution

  • Last year I saw this video from ngConf, which suggested an approach of using decorator for something similar, which I thought was interesting. May be that will help you.

    The idea is to create a decorator and use it for all required changes callback.

    changes.decorator.ts

    export function OnChanges<T>(callback: (newValue: T) => void) {
      const cachedValueKey = Symbol();
      return function(target, key) {
        Object.defineProperty(target, key, {
          set: function(value) {
            if (this[cachedValueKey] === value) {
              return;
            }
    
            this[cachedValueKey] = value;
            callback.call(this, value);
          },
          get: function() {
            return this[cachedValueKey];
          }
        });
      };
    }
    

    Usage in your case:

    @OnChanges<string>((newValue: string) => {
      this.submitSearch();
    })
    @Input()
    productMember: string;
    

    take a look at this stackblitz.