0

我有一个系统,它接受 key:object 对,然后让您稍后在应用程序中获取它们。

问题是这个索引签名会中断输入,因为它允许任何键存在,所以你不能输入 get() 请求。

下面是应用程序和问题的摘要片段。

我试过删除这个索引签名,这是一个问题,因为那时setting[key].valueinclass Configuration不存在。我曾尝试删除基本设置界面,但这基本上会破坏您对输入内容所做的任何更改。我已经尝试了很多辅助函数和守卫来试图强制应用程序意识到它是一个设置。我还没有到我必须接受在 get 方法上不输入的地步。

class Setting {
  constructor(
    public value: number,
    private locked: boolean
  ) { }
}

class Settings {
  [key: string]: Setting; // Comment me out: errors (but typing), leave me in: no errors (no typing)
}

interface SettingsCountryRank extends Settings {
  taiwan: Setting;
  china: Setting;
}

class Configuration<TSettings extends Settings> {
  settings: TSettings;

  public get<U extends keyof TSettings>(key: U): TSettings[U]['value'] {
    return this.settings[key].value;
  }

  constructor(settings: TSettings) {
    this.settings = settings;
  }
}

function main(){
  const test = new Configuration<SettingsCountryRank>({ taiwan: new Setting(1, true), china: new Setting(2, false) });

  test.get('china')
  test.get('notathing');
}

当您打开和关闭线路时,Settings您可以看到问题。

4

1 回答 1

2

我认为您应该使用映射类型,而不是使用索引签名,其键被限制为已知值。我将使用标准库Record<K, V>中定义的映射类型。

重要的是使用 form 的递归约束T extends Record<keyof T, Setting>,它确保 的所有属性都T必须具有 type Setting,但不会对键施加任何约束(索引签名说将键约束为“所有可能的字符串值”,即不是你想要的):

// Settings<T> has the same keys as T, and the values are all Setting
type Settings<T> = Record<keyof T, Setting>;

// constraining SettingsCountryRank to Settings<SettingsCountryRank> is
// makes sure that every declared property has type Setting:
interface SettingsCountryRank extends Settings<SettingsCountryRank> {
    taiwan: Setting;
    china: Setting;
    // oopsie: string; // uncomment this to see an error
}

// constraining TSettings to Settings<TSettings> lets the compiler know that
// all properties of TSettings are of type Setting
class Configuration<TSettings extends Settings<TSettings>> {
    settings: TSettings;

    public get<U extends keyof TSettings>(key: U): TSettings[U]['value'] {
        return this.settings[key].value;
    }

    constructor(settings: TSettings) {
        this.settings = settings;
    }
}

function main() {
    const test = new Configuration<SettingsCountryRank>({ taiwan: new Setting(1, true), china: new Setting(2, false) });
    test.get('china')
    test.get('notathing'); // error as expected
}

我认为这可以按您的预期工作。希望有帮助;祝你好运!

于 2019-04-13T01:55:09.137 回答