给定函数和示例参数,在调用RISK Parser时,我希望defaultValue成为parse函数中的值类型参数,并且仅用于配置对象中的该键.

我try 了各种方法、推断等,但似乎无法将类型与配置中的键相关联.

type Parser<T> = (value: T) => any;

interface ParserOptions<TParser extends Parser<unknown>> {
  parse: TParser;
  defaultValue?: Parameters<TParser>[0];
}

function createParser<
  TValue,
  TParser extends Parser<TValue>,
  TParserOptions extends ParserOptions<TParser>,
  TParsers extends Record<string, TParserOptions>,
  TConfig extends {
    [K in keyof TParsers]: TParsers[K];
  },
>(fields: TConfig) {
  return fields;
}

createParser({
  right_string: {
    defaultValue: 'adf',
    parse(value: string) {
      return value;
    },
  },
  right_number: {
    defaultValue: 1,
    parse(value: number) {
      return value;
    },
  },
  wrong: {
    defaultValue: new Date(),
    parse(value: string) {
      return value;
    },
  },
});

例如,我如何保护此函数调用不允许使用"错误"键.

推荐答案

给出所编写的示例,我将以这种方式处理它,只有一个类型参数:

interface ParserOptions<T> {
  parse: Parser<T>;
  defaultValue?: T;
}

function createParser<T extends object>(fields: {
  [K in keyof T]: ParserOptions<T[K]>
}) {
  return fields;
}

现在createParser()中的T对应于其属性类型是Parser的类型参数的对象.所以当你打电话的时候:

createParser({
  right_string: {
    defaultValue: 'adf',
    parse(value: string) {
      return value;
    },
  },
  right_number: {
    defaultValue: 1,
    parse(value: number) {
      return value;
    },
  },
  wrong: {
    defaultValue: new Date(),
    parse(value: string) { // error
      // Type 'Date' is not assignable to type 'string'.
      return value;
    },
  },
}); 

编译器将T推断为{ right_string: string; right_number: number; wrong: Date; },并根据需要抱怨wrong属性上的parse()方法出错.

这是因为fields‘S字是T的键上的同态mapped type(见What does "homomorphic mapped type" mean?),而打字本通常可以从这种映射的类型中推断出来.

但请注意,编写generic个函数以使推理实现您想要的功能,与其说是一门科学,不如说是一门艺术.有时,所述目标的微小更改将需要对通用调用签名进行较大更改.更糟糕的是,有时轻微的更改会使问题无法解决,然后您不得不放弃或重构以使用其他数据 struct .鉴于您问题中的版本有许多额外的类型参数,这些参数可能有一定的用途,因此不清楚重新添加它们是否能实现该目的.


Playground link to code

Typescript相关问答推荐

从接口创建类型安全的嵌套 struct

即使子网是公共的,AWS CDK EventBridge ECS任务也无法分配公共IP地址

替代语法/逻辑以避免TS变量被分配之前使用." "

typescribe不能使用值来索引对象类型,该对象类型满足具有该值的另一个类型'

Redux—Toolkit查询仅在不为空的情况下添加参数

带占位符的模板文字类型何时扩展另一个?

等待用户在Angular 函数中输入

笛卡尔产品类型

如何通过TypeScrip中的函数防止映射类型中未能通过复杂推理的any值

try 呈现应用程序获取-错误:动作必须是普通对象.使用自定义中间件进行MySQL操作

如何编辑切片器以使用CRUD调用函数?

在打字应用程序中使用Zod和Reaction-Hook-Forms时显示中断打字时出错

有没有一种更好的方法来存储内存中的数据,而不是在类型脚本中使用数组和基于索引的函数?

在打印脚本中将对象类型转换为数组

如何使用angular15取消选中位于其他组件中的复选框

为什么过滤器不改变可能的类型?

带有过滤键的 Typescript 映射类型

如何使用动态生成的键和值定义对象的形状?

React HashRouter,单击导航栏时页面重新加载出现问题

在Typescript 中,是否有一种方法来定义一个类型,其中该类型是字符串子集的所有可能组合?