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

CDK v1转v2后Lodash _.get类型推断异常排查求助

问题根源分析

这个问题的核心是TypeScript版本升级后类型检查更严格,结合你定义的JsonObject递归联合类型,导致Lodash的_.get无法正确推导返回值类型:

  • 旧版TypeScript对泛型的处理更宽松,_.get会默认返回any;新版TS会根据输入的JsonObject类型(包含字符串、数字、布尔、数组、递归对象的联合类型),推导_.get(invocationRule, "Rule")的可能类型为JsonObject | undefined,但因为联合类型的特性,TS无法确定它具体是哪种类型,最终只能推断为undefined。
  • 当你用!断言非空后,TS发现联合类型中只有对象类型能访问属性,但无法确定rule确实是对象,所以访问rule!["expression"]时,所有非对象类型(字符串/数字/布尔/数组)都没有该属性,交叉后类型退化为never,自然会提示startsWith不存在。
解决方案

方案1:为invocationRule定义更精确的接口

放弃宽泛的JsonObject,直接定义符合业务结构的类型,让TS能准确推断:

// 定义具体的规则结构
interface InvocationRule {
  Rule: {
    name: string;
    expression: string;
  };
  Disabled?: boolean;
}

// 修改函数参数类型
private createScheduleRule(scope: Construct, invocationRule: InvocationRule, props: ScheduleProps): events.Rule {
    const rule = invocationRule.Rule; // 直接访问,无需_.get,类型推断完全正确
    return new events.Rule(scope, `${rule.name}Rule`, {
        enabled: !invocationRule.Disabled,
        schedule: rule.expression.startsWith("P")
            ? events.Schedule.rate(cdk.Duration.parse(rule.expression))
            : events.Schedule.expression(`cron(${rule.expression})`)
        // ...其他属性
    });
}

方案2:手动指定_.get的泛型或使用类型断言

如果必须保留JsonObject类型,可以通过泛型或断言告诉TS返回值的具体类型:

private createScheduleRule(scope: Construct, invocationRule: JsonObject, props: ScheduleProps): events.Rule {
    // 方式1:指定_.get的泛型参数
    const rule = _.get<JsonObject, "Rule", { name: string; expression: string }>(invocationRule, "Rule");
    // 方式2:类型断言(更简洁)
    // const rule = _.get(invocationRule, "Rule") as { name: string; expression: string };

    // 保险起见,添加类型守卫避免运行时错误
    if (!rule || typeof rule !== 'object' || !('name' in rule) || !('expression' in rule)) {
        throw new Error("Invalid invocation rule structure");
    }

    return new events.Rule(scope, `${rule.name}Rule`, {
        enabled: !_.get(invocationRule, "Disabled", false),
        schedule: rule.expression.startsWith("P")
            ? events.Schedule.rate(cdk.Duration.parse(rule.expression))
            : events.Schedule.expression(`cron(${rule.expression})`)
        // ...其他属性
    });
}

方案3:优化JsonObject的类型定义

调整递归联合类型的结构,让TS更容易推断对象类型:

// 拆分对象类型和基础类型,避免直接递归联合
type JsonValue = string | number | boolean | JsonValue[];
export type JsonObject = JsonValue | { readonly [key: string]: JsonValue };

这样修改后,TS能更清晰地区分对象和非对象类型,结合类型守卫可以缩小rule的类型范围:

private createScheduleRule(scope: Construct, invocationRule: JsonObject, props: ScheduleProps): events.Rule {
    const rule = _.get(invocationRule, "Rule");
    if (typeof rule !== 'object' || rule === null || !('name' in rule) || typeof rule.name !== 'string' || !('expression' in rule) || typeof rule.expression !== 'string') {
        throw new Error("Invalid Rule structure in invocationRule");
    }

    return new events.Rule(scope, `${rule.name}Rule`, {
        enabled: !_.get(invocationRule, "Disabled", false),
        schedule: rule.expression.startsWith("P")
            ? events.Schedule.rate(cdk.Duration.parse(rule.expression))
            : events.Schedule.expression(`cron(${rule.expression})`)
        // ...其他属性
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:46:04