如何使用嵌套接口作用域TypeScript泛型类型

埃贡·梅杰斯(Egon Meijers)

我试图为接受三个参数的函数创建通用接口。填写第一个参数时,第二个参数的选项应在第一个参数的范围内。然后,第三个参数应在第二个参数的范围内。

我当前的代码如下所示:

type SettingActionCreator<T> = <
  L extends T,
  K extends keyof L,
  C extends keyof L[K]
>(
  type: K,
  settingKey: keyof L[K],
  settingValue: L[K][C]
)

export interface SomeSettings {
  [Type.TypeA]: {
    settingA: "value1" | "value2";
    settingB: "value3 | "value4";
  };
  [Type.TypeB]: {
    ...
  };
  [Type.TypeC]: {
    ...
  };
}

const setSomeSetting: SettingActionCreator<SomeSettings> = (
  type,
  settingKey,
  settingValue
) =>
  // do something

因此,当我想setSomeSetting使用参数调用时,我希望传递给它的每个参数的作用域都会变小。

例如,如果我填写第一个参数,那么SettingActionCreator确保第二个参数(settingKey)只能是settingAsettingB到目前为止,一切正常。

setSomeSetting(Type.TypeA, ....) // <-- settingKey accepts "settingA" and "settingB"

但是对于第三个论点,我似乎无法解决。当我设置第一个参数和第二个参数时,我希望第三个参数仅接受所选settingKey参数中的并集选项但是相反,我得到了所有选择Type.TypeA因此,settingA的settingValuessettingB

使用此代码:

setSomeSetting(Type.TypeA, "settingA", "value3") // <-- settingValue should only accept "value1" or "value2"

我会期望像这样的错误:

TS2345: Argument of type '"value3"' is not assignable to parameter of type `"value1" | "value2"

而是我没有得到任何类型的错误,因为它可同时接收的值settingAsettingB

有人对我做错了什么建议吗?

肖恩·维埃拉(Sean Vieira)

您需要向TypeScript证明settingKey与关联的settingValue-settingKey: keyof L[K]声明中的混淆了它(我不确定为什么-感觉像是一个bug type C extends keyof L[K] != keyof L[K],但无论如何肯定是对类型推断代码的限制)。

将该参数的类型更改为settingKey: C,TypeScript将能够理解这三个参数之间的关系:

type SettingActionCreator<T> = <
  L extends T,
  K extends keyof L,
  C extends keyof L[K]
>(
  type: K,
  settingKey: C, // <-- changed from keyof L[K]
  settingValue: L[K][C]
) => void;


declare const Type: {
  readonly TypeA: unique symbol,
  readonly TypeB: unique symbol,
  readonly TypeC: unique symbol
}

export interface SomeSettings {
  [Type.TypeA]: {
    settingA1: "valueA1" | "valueA2";
    settingA2: "valueA3" | "valueA4";
  },
  [Type.TypeB]: {
    settingB1: "valueB1" | "valueB2",
    settingB2: "valueB3" | "valueB4"
  },
  [Type.TypeC]: {
    //
  }
}

const setSomeSetting: SettingActionCreator<SomeSettings> = (
  type,
  settingKey,
  settingValue
) => {}

这会导致您正在寻找的错误类型:

setSomeSetting(Type.TypeB, "settingB1", "valueA3")
// Argument of type '"valueA3"' is not assignable to parameter of type '"valueB1" | "valueB2"'.

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章