You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Opts的requiredKeys支持Values与customParsers的键集合?

TypeScript 泛型实现动态约束 requiredKeys 范围

问题场景

你当前定义了以下接口:

interface Values {
  height: number;
  width: number;
}

interface Opts {
  requiredKeys: (keyof Values)[];
  customParsers: Record<string, (text: string) => unknown>;
}

希望requiredKeys能同时接受Values的键名和customParsers中定义的键名,比如:

const opts: Opts = {
  requiredKeys: [
    'height', // 合法:属于Values的键
    'foo', // 不合法:既不是Values的键,也未在customParsers中定义
    'x', // 合法:在customParsers中已定义
  ],
  customParsers: {
    x: text => parseInt(text),
  },
};

直接把requiredKeys改成(keyof Opts['customParsers'] | keyof Values)[]无效,需要通过泛型实现动态约束。

解决方案

使用泛型捕获customParsers的具体键名,让requiredKeys的类型与customParsers的键名动态关联:

interface Values {
  height: number;
  width: number;
}

// 用泛型T约束customParsers的结构,同时关联requiredKeys的范围
interface Opts<T extends Record<string, (text: string) => unknown>> {
  requiredKeys: (keyof Values | keyof T)[];
  customParsers: T;
}

用法示例

合法场景

// TypeScript会自动推断customParsers的键为'x',因此requiredKeys允许包含'x'
const validOpts: Opts<{x: (text: string) => number}> = {
  requiredKeys: ['height', 'x'],
  customParsers: {
    x: text => parseInt(text),
  },
};

// 也可以省略泛型参数,让TypeScript自动推断
const validOptsAuto = {
  requiredKeys: ['width', 'y'],
  customParsers: {
    y: text => text.length,
  },
} satisfies Opts<{y: (text: string) => number}>;

非法场景(会触发编译错误)

// 'foo'不在Values的键或customParsers的键中,编译报错
const invalidOpts = {
  requiredKeys: ['height', 'foo'],
  customParsers: {
    x: text => parseInt(text),
  },
} satisfies Opts<{x: (text: string) => number}>;

原理说明

泛型T会捕获customParsers的具体键名和类型,(keyof Values | keyof T)[]让requiredKeys的元素只能是Values的键或者T的键(也就是customParsers中定义的键),这样TypeScript就能在编译时完成精确的类型检查。

内容的提问来源于stack exchange,提问作者wathhr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:02:42