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

TypeScript扩展运算符异常:空映射类型致校验失效如何修复?

问题修复方案

问题根源

当third接口继承base且无额外属性时,Omit<third, keyof base>会得到空类型{}。此时MappedTypeFunc<{}, any>生成的thirdMapped也是空类型,导致thirdFullMapped = baseMapped & {}等价于baseMapped。TypeScript仅对有明确属性定义的类型执行额外属性检查,空类型不会限制多余属性,因此firstObject的firstProp能被混入thirdObjectFull而不触发错误。

修复方案

我们需要让thirdFullMapped在继承baseMapped的同时,明确禁止任何不属于baseMapped的额外属性。通过自定义辅助类型实现这一约束:

步骤1:定义严格组合类型

创建StrictCombine类型,自动处理空扩展类型的场景,为空扩展类型添加禁止额外属性的约束:

type StrictCombine<Base, Extension> = 
  Extension extends {} 
    ? Base & Extension 
    : Base & Record<Exclude<keyof any, keyof Base>, never>;

逻辑说明:如果Extension是空类型,则返回Base加上“禁止所有非Base属性”的索引签名;否则返回正常的交叉类型。

步骤2:替换原有FullMapped类型定义

用StrictCombine替代原有的交叉类型定义,统一处理所有场景:

type firstFullMapped = StrictCombine<baseMapped, firstMapped>;
type secondFullMapped = StrictCombine<baseMapped, secondMapped>;
type thirdFullMapped = StrictCombine<baseMapped, thirdMapped>;

完整修复代码

interface base {
    type: string;
    name: string;
    add: string;
}

interface first extends base {
    firstProp: string  
}

interface second extends base {
    secondProp: string    
}

interface third extends base {

}

type MappedTypeFunc<T, U> = {
    [K in keyof T]: (value: T[K], additionalParam?: U) => any;
} 

type baseMapped = MappedTypeFunc<base, any>

type firstMapped = MappedTypeFunc<Omit<first, keyof base>, any>
type secondMapped = MappedTypeFunc<Omit<second, keyof base>, any>
type thirdMapped = MappedTypeFunc<Omit<third, keyof base>, any>

// 新增严格组合辅助类型
type StrictCombine<Base, Extension> = 
  Extension extends {} 
    ? Base & Extension 
    : Base & Record<Exclude<keyof any, keyof Base>, never>;

// 使用StrictCombine定义完整类型
type firstFullMapped = StrictCombine<baseMapped, firstMapped>;
type secondFullMapped = StrictCombine<baseMapped, secondMapped>;
type thirdFullMapped = StrictCombine<baseMapped, thirdMapped>;

const baseObject: baseMapped = {
    type: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    },
    name: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    },
    add: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    }
}

const firstObject: firstMapped = {
    firstProp: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    }
}

const secondObject: secondMapped = {
    secondProp: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    }
}

const thirdObject: thirdMapped = {}

const firstObjectFull: firstFullMapped = {
    ...baseObject,
    ...firstObject
}
// 依然报错(符合预期)
const secondObjectFull: secondFullMapped = {
    ...baseObject,
    ...firstObject
}

// 现在会触发类型错误:firstProp属性不存在于thirdFullMapped类型中
const thirdObjectFull: thirdFullMapped = {
    ...baseObject,
    ...firstObject
}

效果验证

修复后,thirdObjectFull混入firstObject时,TypeScript会检测到firstProp为多余属性,触发预期的类型错误,与secondObjectFull的行为保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:55:05