Object.keys索引签名的打字稿问题

时间:2019-07-04 05:35:12

标签: typescript

我有以下类型定义:

interface DefaultConfig {
  state: {
    initialState: AllState;
  };
}

type UserConfig = {
  [K in keyof DefaultConfig]: DefaultConfig[K];
};
// Could also use 'type UserConfig = Partial<DefaultConfig>;'

interface AssignDefaults {
  (userConfig: UserConfig): DefaultConfig;
}

我在以下功能中使用它们:

const defaultConfig: DefaultConfig = {
  state: {
    initialState: defaultInitialState
  }
};

const assignDefaults: AssignDefaults = userConfig => {
  const thisUserConfig = userConfig;
  Object.keys(userConfig).forEach(key => {
    if (key in defaultConfig) {
      const maybeObject = userConfig[key];
      if (!!maybeObject && maybeObject.constructor === Object) {
        thisUserConfig[key] = {
          ...(defaultConfig[key] || {}),
          ...userConfig[key]
        };
      }
    }
  });
  return { ...defaultConfig, ...thisUserConfig };
};

我希望发生的是,userConfig[key]应该等于keyof DefaultConfig,因为这就是UserConfig索引签名中定义的内容。

但是,这不起作用,因为Object.keys(...)将其返回值定义为string[]。这会导致Typescript错误:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'UserConfig'.
  No index signature with a parameter of type 'string' was found on type 'UserConfig'.

Typescript似乎无法确定keyof DefaultConfig也是一个字符串。

我知道我可以通过在[key: string]: any界面中加入DefaultConfig来消除此错误,但是我更希望不要这样做:

  1. 这些是其表示的对象所允许的唯一键和值(例如defaultConfig对象不应包含foo: "bar"作为键/值对,但是如果{{1} }包含索引签名。
  2. 当我需要调用DefaultConfig时,我不希望它返回类型为defaultConfig.state.initialState,如果包含该索引签名,则会发生这种情况。与如果我创建一个常量any然后调用const foo = assignDefaults(userConfigObject)相同。
  3. 除非绝对必要,否则我不喜欢在类型定义中使用foo.state.initialState

这是Typescript的限制吗?还是有一些解决方法?

1 个答案:

答案 0 :(得分:0)

我知道了...

- Object.keys(userConfig).forEach(key => {
+ (Object.keys(userConfig) as (keyof DefaultConfig)[]).forEach(key => {