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

如何用TypeScript约束defaultProperty为properties的有效键?

问题:限制defaultProperty必须为properties的有效键

需求是创建一个TypeScript类型,确保defaultProperty的值必须是properties对象的有效键。以下是原始示例:

type TestType = {
  properties: {
    [x: string]: number;
  };
  defaultProperty: string;
};

// 不符合要求但未报错
const invalid: TestType = {
  properties: {
    foo: 123,
  },
  defaultProperty: "not a valid property",
};

// 符合要求
const valid: TestType = {
  properties: {
    foo: 123,
  },
  defaultProperty: "foo",
};

上述代码中,invalid的defaultProperty不是properties的有效键,但TypeScript没有报错。尝试过以下泛型方案,但未达到预期:

type TestType<P = { [p: string]: number }> = {
  properties: P;
  defaultProperty: keyof P;
};

该方案既不会对invalid报错,还会让defaultProperty的类型变为string | number,不符合需求。


解决方案

要实现需求,核心是让TypeScript根据具体的properties对象推断出键的类型,而非使用宽泛的索引签名默认值。以下是两种可行方式:

方式一:泛型函数(推荐)

通过函数创建对象时,TypeScript会自动推断properties的键类型,从而严格约束defaultProperty:

function createConfig<P extends Record<string, number>>(config: {
  properties: P;
  defaultProperty: keyof P;
}) {
  return config;
}

// 报错:类型'"not a valid property"'不能赋值给类型'"foo"'
const invalid = createConfig({
  properties: { foo: 123 },
  defaultProperty: "not a valid property"
});

// 正常通过
const valid = createConfig({
  properties: { foo: 123 },
  defaultProperty: "foo"
});

方式二:泛型类型+显式指定参数

如果需要直接定义变量,可以使用泛型类型,但必须显式指定泛型参数,让TypeScript明确properties的键集合:

type TestType<P extends Record<string, number>> = {
  properties: P;
  defaultProperty: keyof P;
};

// 报错:类型'"not a valid property"'不能赋值给类型'"foo"'
const invalid: TestType<{ foo: number }> = {
  properties: { foo: 123 },
  defaultProperty: "not a valid property"
};

// 正常通过
const valid: TestType<{ foo: number }> = {
  properties: { foo: 123 },
  defaultProperty: "foo"
};

原泛型方案无效的原因

你之前的泛型给了默认值{ [p: string]: number },当未指定泛型参数时,TypeScript会使用这个默认值。而keyof { [p: string]: number }的结果是string | number(因为JS对象键会被隐式转换为字符串或数字),所以无法约束无效键的输入。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:17:32