typescript 在循环中评估模板化配置

jtoj6r0c  于 2023-11-20  发布在  TypeScript
关注(0)|答案(1)|浏览(162)

bounty将在4天后过期。回答此问题有资格获得+300声望奖励。Page not found正在寻找规范答案

我有一个系统配置(由我提供),它描述了用户配置(由用户提供)的能力。
然后我想传递每一个用户配置,并根据系统设置对其进行评估。
为了说明我的意思,这里有一些示例代码。它应该输出2行:

  • 123
  • “无所谓”
const systemConfig = {
  a: (arg: number) => arg,
  b: (arg: string) => arg,
}

type InferConfig<T extends {}> = { [K in keyof T]: T[K] extends (arg: infer U) => any ? U : never }

const userConfig: InferConfig<typeof systemConfig> = {
  a: 123,
  b: 'whateva',
};

// (everything above working as expected)

for (const key in userConfig) {
  if (key in systemConfig) {
    console.log(systemConfig[key](userConfig[key])); // correct output but highlights errors

    console.log(systemConfig[key as keyof typeof systemConfig](userConfig[key as keyof typeof userConfig])); // luckily doesn't work because I want to avoid "as" if possible
  }
}

字符串

Playground

另一个要求是循环(不是代码的工作部分)不能包含“if(key = 'a')...”形式的逻辑(即依赖于a

xnifntxz

xnifntxz1#

明白了,类型推断无法验证userConfig[key]systemConfig[key]的有效参数。这应该有助于减轻你的痛苦。

function callSystemConfig<K extends keyof typeof systemConfig>(
  key: K,
  arg: K extends keyof InferConfig<typeof systemConfig> ? InferConfig<typeof systemConfig>[K] : never
) {
  return systemConfig[key](arg as any as never);  // Use 'as any as never' to bypass strict type checking, not he most beautiful solution.
}

const systemConfig = {
  a: (arg: number) => arg,
  b: (arg: string) => arg,
};

type InferConfig<T> = { [K in keyof T]: T[K] extends (arg: infer U) => any ? U : never };

const userConfig: InferConfig<typeof systemConfig> = {
  a: 123,
  b: 'whateva',
};

for (const key in userConfig) {
  if (key in systemConfig) {
    const systemKey = key as keyof typeof systemConfig;
    console.log(callSystemConfig(systemKey, userConfig[systemKey]));
  }
}

字符串
操场

相关问题