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

TypeScript对象转单属性联合类型:如何限制额外属性报错?

问题:限制联合类型返回值仅包含指定属性

我需要将TypeScript对象的每个属性转换为独立对象的联合类型,例如:

{
 200: number;
 500: string;
}

转换为:

{
 200: number;
 500?: undefined;
} |
{
 500: string;
 200?: undefined;
}

目前已实现上述转换,但返回结果中包含额外属性时不会触发错误——比如返回{100: "why no error", 200: 100}时无报错,需要修改代码让这种情况触发错误。

原代码如下:

type AllKeys<T> = T extends unknown ? keyof T : never;
type Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
type _ExclusifyUnion<T, K extends PropertyKey> = T extends unknown
  ? Id<T & Partial<Record<Exclude<K, keyof T>, never>>>
  : never;
type ExclusifyUnion<T> = _ExclusifyUnion<T, AllKeys<T>>;
type split_return_type<T> = {
  [K in keyof T]: { [P in K]: T[P] };
};
type ValueOf<T> = T[keyof T];
export type SchemezLayoutReturnType<T> = Promise<
  ExclusifyUnion<ValueOf<split_return_type<Required<T>>>>
>;

function TestFnx<T>(input: T, handleAsync: () => SchemezLayoutReturnType<T>) {
    return {
        input,
        handleAsync,
    }
}

type required_return_type = {
    200: number;
    500: string;
}
const rrr: required_return_type = {
    200: 100,
    500: "00"
};
TestFnx(rrr, async () => {
    return {
        100: "200",
        200: 100,
        // 500: "oii",
    }
});

解决方案

要禁止额外属性,需在联合类型的每个成员中明确禁止所有未指定的键,修改核心类型定义即可实现:

修改后的完整代码

type AllKeys<T> = T extends unknown ? keyof T : never;
type Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
// 替换原_ExclusifyUnion,添加对额外键的严格限制
type _ExclusifyUnion<T, K extends PropertyKey> = T extends unknown
  ? Id<
      T & {
        // 限制原始类型中存在但当前成员没有的键只能为undefined
        [P in Exclude<K, keyof T>]?: never;
      } & {
        // 严格禁止所有不在原始类型键集合中的额外属性
        [Q in Exclude<PropertyKey, K>]?: never;
      }
    >
  : never;
type ExclusifyUnion<T> = _ExclusifyUnion<T, AllKeys<T>>;
type split_return_type<T> = {
  [K in keyof T]: { [P in K]: T[P] };
};
type ValueOf<T> = T[keyof T];
export type SchemezLayoutReturnType<T> = Promise<
  ExclusifyUnion<ValueOf<split_return_type<Required<T>>>>
>;

function TestFnx<T>(input: T, handleAsync: () => SchemezLayoutReturnType<T>) {
    return {
        input,
        handleAsync,
    }
}

type required_return_type = {
    200: number;
    500: string;
}
const rrr: required_return_type = {
    200: 100,
    500: "00"
};
TestFnx(rrr, async () => {
    return {
        100: "200", // 此处触发错误:类型“string”不能赋值给类型“undefined”
        200: 100,
        // 500: "oii",
    }
});

实现原理

  • 原类型仅处理了原始对象中存在但当前联合成员缺失的键,未限制完全不在原始对象中的额外键。
  • 添加[Q in Exclude<PropertyKey, K>]?: never;后,所有不在原始对象键集合K中的属性都会被标记为只能赋值undefined,若给这些键赋值其他类型则直接报错。
  • 使用?: never而非never,是因为联合类型的每个成员仅需保留自身的必填键,其他键允许不存在,但禁止赋予非undefined的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:02:07