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

如何在TypeScript中基于另一对象属性定义对象类型?

解决方案:通过条件类型+精确类型推导实现关联

你的需求完全可以实现!核心问题在于两个点:一是需要把ParameterDesc里的字符串类型标识(比如'number')映射成TypeScript的原始类型(number),二是要让someConfig的类型保留足够精确的信息,这样TypeScript才能正确推导每个属性对应的类型。

下面是具体的实现步骤:

1. 创建类型映射工具

首先定义一个条件类型,用来把ParameterDesc的子类型转换成对应的TS原始类型:

type TypeFromDesc<T extends ParameterDesc> = 
  T extends NumberParameterDesc ? number :
  T extends StringParameterDesc ? string :
  T extends BooleanParameterDesc ? boolean :
  never;

2. 重构State类型

用上面的工具类型替换你之前直接取.type的写法,让索引类型能正确解析每个属性的类型:

type State<PDesc extends ParameterDescriptions> = {
  [K in keyof PDesc]: TypeFromDesc<PDesc[K]>;
};

3. 让someConfig保留精确类型

注意!如果直接给someConfig标注ParameterDescriptions类型,TypeScript会把每个属性都当成ParameterDesc联合类型,丢失具体的子类型信息(比如NumberParameterDesc),这样条件类型无法正确工作。

我们可以用一个辅助函数来约束someConfig符合ParameterDescriptions结构的同时,保留精确的类型推导:

const createConfig = <T extends ParameterDescriptions>(config: T) => config;

const someConfig = createConfig({
  someNumProperty: {
    name: 'numPropert',
    type: 'number',
    defaultValue: 42,
  },
  someStrProperty: {
    name: 'strPropert',
    type: 'string',
    defaultValue: 'some default value',
  },
  someBoolProperty: {
    name: 'boolProperty',
    type: 'boolean',
    defaultValue: false,
  },
});

4. 自动生成MyState

现在只需要基于someConfig的类型来定义MyState,它会自动继承所有属性和对应类型:

// 用类型别名直接生成
type MyState = State<typeof someConfig>;

// 或者用interface继承(效果一致)
interface MyState extends State<typeof someConfig> {}

此时MyState的结构完全和你手动定义的一致:

// 等价于:
interface MyState {
  someNumProperty: number;
  someStrProperty: string;
  someBoolProperty: boolean;
}

为什么之前的方法不生效?

你之前的State类型直接取PDesc[property].type,得到的是字符串字面量类型(比如'number'),而不是TypeScript的number原始类型。通过条件类型TypeFromDesc,我们把字符串标识和实际类型做了映射,解决了这个问题。另外,确保someConfig的类型足够精确是关键,否则TypeScript无法区分不同的ParameterDesc子类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:52:17