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

如何定义不允许包含指定字段(甚至不能设为undefined)的对象类型?

问题描述

编写了合并对象的TypeScript函数,希望在编译阶段阻止addition参数包含baseField字段(即使设为undefined),避免运行时覆盖原对象的字段。现有方案使用baseField?: never无法检测到设为undefined的情况,导致编译不报错但运行时baseField被意外覆盖。

原实现代码:

interface BaseType {
    baseField: string;
}

function combine<T extends Object>(base: BaseType, addition: T) {
    if('baseField' in addition)
        throw new Error('addition should not have baseField');
    return {...base, ...addition};
}

const myBase : BaseType = {
    baseField: "xyz"
}

const myAddition = {
    otherField: 123
}

const ret = combine(myBase, myAddition);
// --> ret = { baseField: "xyz", otherField: 123}
console.log(ret);

尝试的无效方案:

interface BaseType {
    baseField: string;
}

type RestrictionType = Object & {
    baseField?: never
}

function combine<T extends RestrictionType>(base: BaseType, addition: T) {
    return {...base, ...addition};
}

const myBase : BaseType = {
    baseField: "xyz"
}

const myAddition = {
    otherField: 123,
    baseField: undefined // 显式设为undefined
}

const ret = combine(myBase, myAddition); // 无编译警告,但运行时baseField被覆盖
// --> ret = { baseField: undefined, otherField: 123 }
console.log(ret);
解决方案

要实现绝对禁止对象包含指定字段(无论值是什么),可以通过约束泛型类型的键与禁止键完全不相交来实现:

  1. 定义类型工具,检查对象是否包含禁止键,若包含则返回never触发编译错误:
// 禁止T包含U中的任何键
type ProhibitKeys<T, U extends object> = keyof T extends Exclude<keyof T, keyof U> ? T : never;
  1. 修改combine函数的泛型约束,确保addition参数符合要求:
interface BaseType {
    baseField: string;
}

type ProhibitKeys<T, U extends object> = keyof T extends Exclude<keyof T, keyof U> ? T : never;

function combine<T extends ProhibitKeys<T, BaseType>>(base: BaseType, addition: T) {
    return {...base, ...addition};
}

const myBase: BaseType = {
    baseField: "xyz"
}

// 合法:无baseField字段
const validAddition = {
    otherField: 123
}
const ret1 = combine(myBase, validAddition); // 编译通过

// 非法:显式设置baseField为undefined
const invalidAddition1 = {
    otherField: 123,
    baseField: undefined
}
const ret2 = combine(myBase, invalidAddition1); // 编译错误:类型不满足约束

// 非法:显式设置baseField为字符串
const invalidAddition2 = {
    otherField: 123,
    baseField: "abc"
}
const ret3 = combine(myBase, invalidAddition2); // 编译错误

原理说明

  • keyof T extends Exclude<keyof T, keyof U>:检查T的所有键是否都不在U的键集合中。如果T包含U的任意键,Exclude<keyof T, keyof U>会排除这些键,导致keyof T与排除后的类型不匹配,最终返回never触发编译错误。
  • 这种约束会严格检查对象的键,无论对应值是undefined还是其他类型,只要存在禁止键就会报错,彻底避免运行时覆盖问题。

内容的提问来源于stack exchange,提问作者Hauke P.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 11:42:45