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

TypeScript联合类型函数使用或运算符时的属性不存在问题

问题解决:TypeScript联合类型属性访问报错

错误信息翻译

类型'NotificationObjectType | ContentType | FormValues'上不存在属性'fallbackLanguage'。类型'ContentType'上不存在属性'fallbackLanguage'。

类型'NotificationObjectType | ContentType | FormValues'上不存在属性'language'。类型'NotificationObjectType'上不存在属性'language'。

问题原因

函数参数property是三种类型的联合,但这三个类型的属性不统一:

  • ContentType没有fallbackLanguage属性
  • NotificationObjectType没有language属性

TypeScript的严格类型检查要求:访问联合类型的属性时,该属性必须存在于联合的所有成员中。因为它无法确定当前property具体是哪一种类型,所以不允许直接访问仅存在于部分成员的属性。

解决方案

方案1:用in操作符做类型窄化

直接通过in判断属性是否存在,以此窄化property的类型,确保访问属性时类型安全:

export const displayLanguageLabel = (
    objects: { value: string; label: string }[],
    property: NotificationObjectType | FormValues | ContentType,
) => {
    let targetLang: string;
    
    if ('fallbackLanguage' in property) {
        // 此时property被窄化为 NotificationObjectType | FormValues
        targetLang = property.fallbackLanguage || property.language;
    } else if ('language' in property) {
        // 此时property被窄化为 ContentType | FormValues
        targetLang = property.language;
    } else {
        // 处理极端情况:如果某个类型既没有fallbackLanguage也没有language
        // 可根据业务需求返回undefined或抛出错误
        return undefined;
    }
    
    return objects.find((lang) => lang.value === targetLang);
};

方案2:定义类型谓词(Type Predicate)

如果需要在多个地方复用类型判断逻辑,可以自定义类型谓词函数,让类型窄化更清晰:

// 自定义类型谓词,判断对象是否有fallbackLanguage
function hasFallbackLanguage(obj: unknown): obj is NotificationObjectType | FormValues {
    return typeof obj === 'object' && obj !== null && 'fallbackLanguage' in obj;
}

// 自定义类型谓词,判断对象是否有language
function hasLanguage(obj: unknown): obj is FormValues | ContentType {
    return typeof obj === 'object' && obj !== null && 'language' in obj;
}

export const displayLanguageLabel = (
    objects: { value: string; label: string }[],
    property: NotificationObjectType | FormValues | ContentType,
) => {
    let targetLang: string;
    
    if (hasFallbackLanguage(property)) {
        targetLang = property.fallbackLanguage || property.language;
    } else if (hasLanguage(property)) {
        targetLang = property.language;
    } else {
        return undefined;
    }
    
    return objects.find(lang => lang.value === targetLang);
};

方案3:统一类型接口(推荐长期维护)

如果这三个类型都属于“包含语言信息”的对象,可以定义一个公共接口,让所有类型扩展这个接口,从根源上统一类型结构:

// 定义公共接口,包含可选的语言相关属性
interface LanguageCarrier {
    fallbackLanguage?: string;
    language?: string;
}

// 让你的三个类型都扩展这个接口(如果原有类型是自定义的)
type NotificationObjectType = LanguageCarrier & {
    // 这里写NotificationObjectType原有的其他属性
    id: string;
    // ...
};

type FormValues = LanguageCarrier & {
    // FormValues原有的其他属性
    title: string;
    // ...
};

type ContentType = LanguageCarrier & {
    // ContentType原有的其他属性
    content: string;
    // ...
};

// 现在函数参数可以直接用LanguageCarrier,访问属性不会报错
export const displayLanguageLabel = (
    objects: { value: string; label: string }[],
    property: LanguageCarrier,
) => objects.find(lang => lang.value === (property.fallbackLanguage || property.language));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 06:36:13