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.