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

如何为带索引签名的对象类型关联内层与顶层属性?

如何在顶层属性未知时约束对象的嵌套属性?

先看一个已知可行的场景:当顶层属性是固定联合类型时,我们可以通过遍历联合成员来约束子属性的前缀:

type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;

type Obj = { 
    [K in "prop_a" | "prop_b" | "prop_c"]: {
        [P in `${K}${Digit}`]: unknown;
    }
}

这段代码的效果是:每个顶层属性(比如prop_a)的子对象,只能包含prop_a0到prop_a9这些属性,前缀和顶层键严格对应。

问题

如果顶层属性的名称是未知的(不是固定的联合类型),能不能实现同样的约束?也就是不管用户定义什么顶层键,对应的子属性必须是「顶层键+0-9数字」的格式?

错误的尝试

直接用string作为索引签名的写法无法实现约束:

type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;

type Obj = { 
    [K in string]: {
        [P in `${K}${Digit}`]: unknown;
    }
}

这种写法下,内层属性的前缀和顶层键没有关联,不符合预期的代码不会报错:

declare const obj: Obj;

// 本应报错(前缀不是"whatever"),但当前类型定义下不会
obj.whatever.it_should_error0;

// 只有这些才是符合预期的合法属性
obj.whatever.whatever0;
obj.whatever.whatever1;
// ... 直到whatever9

正确的解决方案

需要用泛型来关联顶层键和子属性的前缀,具体实现如下:

type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;

// 泛型类型,T代表所有顶层键的类型
type ConstrainedObj<T extends string> = {
    [K in T]: {
        [P in `${K}${Digit}`]: unknown;
    }
};

// 用法1:明确指定顶层键类型
type SpecificObj = ConstrainedObj<"foo" | "bar">;
declare const specificObj: SpecificObj;
specificObj.foo.foo0; // 合法
specificObj.foo.bar0; // 报错,符合预期

// 用法2:通过泛型函数自动推断顶层键
function createObj<T extends string>(obj: ConstrainedObj<T>): ConstrainedObj<T> {
    return obj;
}

// 传入对象时,TypeScript会自动约束子属性必须匹配顶层键
const myObj = createObj({
    whatever: {
        whatever0: null,
        whatever5: "hello",
        // it_should_error0: 123, // 取消注释会报错,符合预期
    },
    anotherKey: {
        anotherKey9: true,
    }
});

原理说明

泛型T会捕获所有顶层键的具体类型,当遍历K in T时,每个K都是当前顶层键的具体值,因此子属性P in ${K}${Digit}``会被严格约束为「当前顶层键+数字」的格式,完美实现了顶层属性未知时的关联约束。

内容的提问来源于stack exchange,提问作者Andrea Simone Costa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:01:51