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

TypeScript中如何限制对象仅使用指定对象的键?

问题

现有如下TypeScript代码定义了MY_OBJECT:

export type ObjectDetails = {
    a: string,
    b?: string
};

export type MyObjectType = { [key: string]: ObjectDetails };

export const MY_OBJECT: MyObjectType = {
    BANANA: {
        a: "a"
    },
    LEMON: {
        a: "A"
    }
}

export type MyObjectKey = keyof typeof MY_OBJECT;

需要定义类型MyType,要求对应的对象只能使用MY_OBJECT中的键(无需全部使用),值类型为string或number。当前定义的MyType如下:

type MyType = { [key: MyObjectKey]: string | number };

但创建包含非MY_OBJECT键的对象时未触发编译错误,例如:

const newObject: MyType = {
    BANANA: "banana",
    APPLE: "apple" // <-- 此处应触发编译错误,但实际没有
};

推测原因是MyObjectType的键类型设为string,导致MyObjectKey实际为string。请问无需提前定义MY_OBJECT所有键的类型,该如何修改代码实现需求?

解决方法

问题核心在于你给MY_OBJECT显式指定了MyObjectType类型,这个类型的键是string,导致TypeScript无法从字面量推导MY_OBJECT的具体键集合。要让TypeScript保留MY_OBJECT的字面量键信息,有两种可行方案:

方案1:用as const推导字面量类型

去掉MY_OBJECT的显式类型标注,改用as const让TypeScript保留具体的键和值的字面量类型:

export type ObjectDetails = {
    a: string,
    b?: string
};

// 去掉MyObjectType标注,用as const锁定字面量结构
export const MY_OBJECT = {
    BANANA: {
        a: "a"
    },
    LEMON: {
        a: "A"
    }
} as const;

// 此时MyObjectKey会被推导为"BANANA" | "LEMON"
export type MyObjectKey = keyof typeof MY_OBJECT;

// 用Partial+Record定义可选的合法键类型
type MyType = Partial<Record<MyObjectKey, string | number>>;

这时再创建包含非法键的对象,就会触发编译错误:

const newObject: MyType = {
    BANANA: "banana",
    APPLE: "apple" // 报错:“APPLE”不在类型“Partial<Record<"BANANA" | "LEMON", string | number>>”中
};

方案2:用satisfies约束结构同时保留键信息

如果需要确保MY_OBJECT符合MyObjectType的结构要求,可以用TypeScript 4.9+支持的satisfies关键字,既约束对象结构,又保留字面量键的推导:

export type ObjectDetails = {
    a: string,
    b?: string
};

export type MyObjectType = { [key: string]: ObjectDetails };

// satisfies确保MY_OBJECT符合MyObjectType,同时不丢失字面量键信息
export const MY_OBJECT = {
    BANANA: {
        a: "a"
    },
    LEMON: {
        a: "A"
    }
} satisfies MyObjectType;

export type MyObjectKey = keyof typeof MY_OBJECT;

type MyType = Partial<Record<MyObjectKey, string | number>>;

这个方案兼顾了结构约束和键的精确推导,同样能对非法键触发编译错误。

原代码无效的原因

原代码中MY_OBJECT被显式标注为MyObjectType,而MyObjectType的键是string,所以typeof MY_OBJECT的键类型被抹平为string,MyObjectKey也就变成了string。此时{ [key: string]: string | number }允许任意字符串键,自然不会对APPLE这类键报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:23:29