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

TS编译器为何认为值可能是{}?如何解决该类型赋值报错

TypeScript泛型函数类型错误分析与解决

一、& {}的来源解释

报错里的& {}是TypeScript处理非空判断时的内部类型缩小逻辑:
当你通过if (objId === undefined || objId === null)排除了null和undefined后,TypeScript会用& {}来过滤掉这两个空值类型(因为null & {}和undefined & {}都会被解析为never)。但在泛型上下文里,TypeScript没办法自动推导出去掉空值后的类型就是MyId,所以它只能用T[MyIdProp<T>] & {}来表示非空的属性值类型,而这个类型和MyId之间没有被TypeScript识别为可赋值的关系,因此触发了2322错误。

二、解决方法

这里提供三种可行的解决方式,按需选择:

1. 类型断言快速解决

既然你已经通过代码逻辑确保了objId不是null或undefined,直接用类型断言告诉TypeScript它就是MyId即可:

function doSomething<T extends object>(obj: T, idAttr: MyIdProp<T>): MyId {
    const objId = obj[idAttr];
    if (objId === undefined || objId === null) {
        throw new Error('No ID supplied!');
    }

    return objId as MyId;
}

2. 优化MyIdProp的类型定义

调整类型定义,让TypeScript更清晰地关联属性类型与MyId的关系:

export type MyId = string | number;

// 明确筛选值为MyId或undefined的属性键
export type MyIdProp<T extends object> = {
    [K in keyof T]: T[K] extends MyId | undefined ? K : never
}[keyof T];

// 定义非空ID的类型
type NonNullableMyId<T extends object> = Exclude<T[MyIdProp<T>], null | undefined>;

function doSomething<T extends object>(obj: T, idAttr: MyIdProp<T>): MyId {
    const objId = obj[idAttr];
    if (objId === undefined || objId === null) {
        throw new Error('No ID supplied!');
    }

    return objId as NonNullableMyId<T>;
}

3. 用where子句强化泛型约束(推荐,TypeScript 4.7+)

利用TypeScript的where子句直接约束属性类型,让TypeScript自动推导非空后的类型:

export type MyId = string | number;

function doSomething<T extends object, K extends keyof T>(
    obj: T, 
    idAttr: K
): MyId 
where T[K] extends MyId | undefined {
    const objId = obj[idAttr];
    if (objId === undefined || objId === null) {
        throw new Error('No ID supplied!');
    }

    return objId; // 此处无需断言,TypeScript可正确识别类型
}

内容的提问来源于stack exchange,提问作者F-H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:15:55