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

如何让TypeScript将字符串用作联合类型的键以消除索引错误?

TypeScript联合类型索引报错的解决方法

问题场景

原代码如下:

type Point = {
    x: number, y: number
};

type Point3D = Point & {
    z: number
}
function printPoint(p: Point | Point3D) {
    log("Point {");
    for (const coordinate in p) {
        log("\t", p[coordinate])
    }
    log("}")
}
printPoint({ x: 1, y: 2, z: 3 })
printPoint({ x: 0.4, y: 4 })

这段代码触发错误:Element implicitly has an 'any' type because expression of type 'string' can't be used to index type ..

尝试了以下写法,仅第一种有效,其余均无效:

// 有效
for (const coordinate in p) {
        log("\t", p[coordinate as keyof Point])
   }
// 无效
for (const coordinate in p) {
        log("\t", p[coordinate as keyof Point3D])
    }
// 也无效
for (const coordinate in p) {
        log("\t", p[coordinate as keyof Point | keyof Point3D])
    }

请问如何正确处理,让字符串索引能适用于联合/交叉类型?

解决方法

方法1:使用keyof typeof p断言

直接将循环变量断言为当前参数p的键类型,TypeScript会根据传入的p的实际类型推断出对应的键:

function printPoint(p: Point | Point3D) {
    log("Point {");
    for (const coordinate in p) {
        log("\t", p[coordinate as keyof typeof p])
    }
    log("}")
}

方法2:泛型约束函数参数

通过泛型让TypeScript明确参数p的具体类型,避免联合类型带来的模糊性:

function printPoint<T extends Point | Point3D>(p: T) {
    log("Point {");
    for (const coordinate in p) {
        log("\t", p[coordinate as keyof T])
    }
    log("}")
}

方法3:断言为通用记录类型(类型安全性稍弱)

如果确定所有属性值都是number类型,可以将p断言为Record<string, number>,这种写法更简洁但会丢失部分类型检查:

function printPoint(p: Point | Point3D) {
    log("Point {");
    const numPoint = p as Record<string, number>;
    for (const coordinate in numPoint) {
        log("\t", numPoint[coordinate])
    }
    log("}")
}

为什么之前的写法无效?

  • 断言为keyof Point有效,是因为x、y是Point和Point3D共有的属性,无论p是哪种类型,这两个键都必然存在。
  • 断言为keyof Point3D无效,是当p为Point类型时,它不存在z属性,TypeScript会拦截这种可能的非法属性访问。
  • keyof Point | keyof Point3D等价于keyof Point3D(因为keyof Point是x|y,和x|y|z联合后还是x|y|z),同样存在访问Point不存在的z属性的风险,因此报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:36:22