简体   繁体   中英

Is it possible to define a type for property names in TypeScript

So i have this constants class which defines the names of the variables that i save to the localStorage / chrome.storage and what their default value is if the items doesn't exist in the storage.

SettingsConstants.ts

export class SettingsConstants {
  public static SETTINGS_ALLOWED: string = "settingsAllowed";
  public static QUIT_ALLOWED: string = "quitAllowed";

  public static DEFAULTS: any = () => {
    const defaults = {};
    defaults[SettingsConstant.SETTINGS_ALLOWED] = true;
    defaults[SettingsConstant.QUIT_ALLOWED] = true;
    return defaults;
  };

  public static STORAGE_STRINGS: string[] = [
      SettingsConstant.SETTINGS_ALLOWED,
      SettingsConstant.QUIT_ALLOWED
    ]
}

Then i have SettingsService which uses these constants in the getItemsFromStorage() method. Basically what it does is that it loops through the strings defined in SettingsConstants and sets it own properties equal to the value it got from the storage , otherwise set the default value .

SettingsService.ts

export class SettingsService implements ISettingsService {

  private settingsAllowed: boolean = undefined;
  private quitAllowed: boolean = undefined;

   constructor(logger: Logger) {
     this.logger = logger;
     this.getItemsFromStorage();
   }

   private getItemsFromStorage(): void {
    const storageStrings: string[] = SettingsConstant.STORAGE_STRINGS;
    for (let i = 0; i < storageStrings.length; i++) {
      const currentString = storageStrings[i];
      if (!this.hasOwnProperty(currentString)) {
        throw "The property is not defined, " +
        "check if it matches the STORAGE_STRING in SettingsConstants";
      }
      const currentItem = this.getItem(currentString);
      this[currentString] = currentItem === undefined
        ? SettingsConstant.DEFAULTS()[currentString]
        : currentItem;
      this.logger.log(currentString, "=", this[currentString]);
    }
  }

  private getItem(item: any): any {
    const localItem: string = localStorage.getItem(item);
    if (localItem === undefined || localItem === null || localItem === 'undefined') {
      return undefined;
    } else {
      return JSON.parse(localItem);
    }
  }
}

The code works, but it isn't statically checked, which is what i desire. The current way to check if SettingsService has a property is to set the property to undefined then use

if (!this.hasOwnProperty(currentString)) {
    throw "The property is not defined, " +
    "check if it matches the STORAGE_STRING in SettingsConstants";
}

To check if the variable exists in the class , if it doesn't then it must mean that we might have misspelled it, or forgotten to add it.

I could solve this problem by adding them to the ISettingsService interface , that would however mean that the property would become public which is not the intention

My desired solution

I would like to define a type where i could define the names of the variables that were allowed to be used. Similar to this

export declare namespace SettingsTypes{
  type SettingsType = "settingsAllowed" | "quitAllowed";
}

Then in SettingsService i could write the following

private settingsAllowed: SettingsTypes.SettingType: boolean;

So its like settingsAllowed name has to be of type SettingsTypes.SettingType and its return type would be boolean

However this does not seem to make much sense, and it seems like there is no way to do this properly, so i was wondering if any of you bright heads might have a great solution for this problem.

It's an interesting question. I went to read some documentation. Have a look at the section of the type guards in particular. Perhaps you can do something similar where you do a type guard for boolean?

function isSetting(setting: any): setting is Settings {
return typeof  setting === SettingsTypes.SettingType;
}

Something similar to this. It's just a possible idea

Advanced Types

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM