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

TypeScript中如何定义基于键约束值的映射类型?

问题分析与解决

问题原因

你定义的Mapping类型使用了[T in string]这种字符串索引签名,但TypeScript处理这类索引签名时,会将每个属性的类型统一推断为Wrapper<string>——因为string是所有字符串字面量的超类型,Wrapper<T>里的T会被自动拓宽为string,导致键和值的类型约束关系完全丢失。所以无论你给键"a"赋值什么字符串类型的value,TypeScript都会认为是合法的,不会触发编译错误。

正确实现方式

要让键K和对应的value类型K严格绑定,需要用泛型约束整个映射对象,而非字符串索引签名。以下是几种可行的写法:

1. 泛型Mapping类型

定义一个接受键集合泛型参数的Mapping类型:

type Wrapper<T extends string> = {
    value: T
}

// T是允许的键的集合,每个键K对应Wrapper<K>
type Mapping<T extends string> = {
    [K in T]: Wrapper<K>
}

使用时显式指定键的类型,此时赋值错误的value会触发编译报错:

// 报错:类型"b"不能赋值给类型"a"
const mapping: Mapping<"a"> = {
    "a": { value: "b" },
}

2. 用satisfies结合const断言

如果不想显式指定泛型,可利用satisfies运算符让TypeScript自动推导键的类型并做约束:

type Wrapper<T extends string> = {
    value: T
}

// 报错:类型"b"不能赋值给类型"a"
const mapping = {
    "a": { value: "b" },
} as const satisfies { [K in keyof typeof mapping]: Wrapper<K> }

3. 泛型工厂函数

最灵活的方式是用泛型函数创建映射,自动推导键的类型并约束value:

type Wrapper<T extends string> = {
    value: T
}

function createMapping<T extends string>(obj: { [K in T]: Wrapper<K> }) {
    return obj;
}

// 报错:类型"b"不能赋值给类型"a"
const mapping = createMapping({
    "a": { value: "b" },
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:02:36