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

TypeScript报错:Type 'null'不能用作索引类型求助

TypeScript错误:Type 'null' cannot be used as an index type 解决方案

问题描述

在前端CRM系统使用TypeScript执行基础计算时,遇到报错:TypeScript- Type 'null' cannot be used as an index type。尽管已通过IF语句判断分数选项是否为null,但错误仍出现在SectionAScore = scoreMap[ScoreOptionA];及类似的百分比赋值代码处。

原代码如下:

export async function CalculateAverageScore() {
    console.log(`CalculateAverage JS Triggered`);

    try {
        console.log(`Calculate Average Score  JS try`);
        const ScoreOptionA: Xrm.Attributes.OptionSetAttribute = FORM_CONTEXT.getAttribute("dp_testweightedaverage");
        const PercentageOptionA: Xrm.Attributes.OptionSetAttribute = FORM_CONTEXT.getAttribute("dp_percentagevalue");
        const ScoreOptionB: Xrm.Attributes.OptionSetAttribute = FORM_CONTEXT.getAttribute("dp_average2");
        const PercentageOptionB: Xrm.Attributes.OptionSetAttribute = FORM_CONTEXT.getAttribute("dp_percentagevalue2");
        const ScoreOptionC: Xrm.Attributes.OptionSetAttribute = FORM_CONTEXT.getAttribute("dp_pickascorefirmwide");
        const PercentageOptionC: Xrm.Attributes.OptionSetAttribute = FORM_CONTEXT.getAttribute("dp_percentagevaluefirmwide");
        // Define Scoring & Percentages 
        const scoreMap: {
            [Score: number]: number
        } = {
            778180000: 1,
            778180001: 2,
            778180002: 3,
            778180003: 4,
            778180004: 5
        };
        const percentageMap: {
            [Percentage: number]: number
        } = {
            778180000: 0.10,
            778180001: 0.20,
            778180002: 0.30,
            778180003: 0.40,
            778180004: 0.50
        };
        FORM_CONTEXT.getAttribute<Xrm.Attributes.OptionSetAttribute>('preferredcontactmethodcode')?.getValue();
        var SectionAScore, SectionAPercentage, SectionBScore, SectionBPercentage, SectionCScore, SectionCPercentage;
        // Section A Score & Percentages 
        if (ScoreOptionA != null && PercentageOptionA != null) {
            ScoreOptionA.getValue();
            PercentageOptionA.getValue();
            SectionAScore = scoreMap[ScoreOptionA];
            SectionAPercentage = scoreMap[ScoreOptionB];
        }
        //Section B Set Score & Percentages
        if (ScoreOptionB != null && PercentageOptionB != null) {
            var ScoreValueB = ScoreOptionB.getValue();
            var valuePercentageB = PercentageOptionB.getValue();
            SectionBScore = scoreMap[ScoreValueB];
            SectionBPercentage = percentageMap[valuePercentageB];
        }
        // Section C Score & Percentages 
        if (ScoreOptionC != null && PercentageOptionC != null) {
            var ScoreValueC = ScoreOptionC.getValue();
            var valuePercentageC = PercentageOptionC.getValue();
            SectionCScore = scoreMap[ScoreValueC];
            SectionCPercentage = percentageMap[valuePercentageC];
        }
        // Calculations
        var Section1Score = (SectionAScore * SectionAPercentage);
        var Section2Score = (SectionBScore * SectionBPercentage);
        var Section3Score = (SectionCScore * SectionCPercentage);
        var averagescore = (Section1Score + Section2Score + Section3Score);
        // Set Average Score Value
        FORM_CONTEXT.getAttribute("dp_decimal").setValue(averagescore);
    }
    catch (error) {
        console.log(`exampleFunction error`, error);
        HELPERS.displayErrorMessage(error);
    }
    finally {
        console.log(`exampleFunction finally`);
    }
}

错误原因分析

  1. 类型与使用不匹配:Section A代码中直接用ScoreOptionA(OptionSetAttribute对象)作为索引访问scoreMap,且误用ScoreOptionB去赋值SectionAPercentage,完全不符合映射表的索引类型要求。
  2. getValue()返回值可能为null:即使OptionSetAttribute对象不为null,getValue()方法在未选择选项时会返回null,TypeScript会识别这个潜在的null值,导致索引类型报错。
  3. 变量未初始化:分数、百分比变量未设置默认值,后续计算可能出现NaN问题。

修复后的代码

export async function CalculateAverageScore() {
    console.log(`CalculateAverage JS Triggered`);

    try {
        console.log(`Calculate Average Score  JS try`);
        // 修正类型声明:getAttribute可能返回null
        const ScoreOptionA: Xrm.Attributes.OptionSetAttribute | null = FORM_CONTEXT.getAttribute("dp_testweightedaverage");
        const PercentageOptionA: Xrm.Attributes.OptionSetAttribute | null = FORM_CONTEXT.getAttribute("dp_percentagevalue");
        const ScoreOptionB: Xrm.Attributes.OptionSetAttribute | null = FORM_CONTEXT.getAttribute("dp_average2");
        const PercentageOptionB: Xrm.Attributes.OptionSetAttribute | null = FORM_CONTEXT.getAttribute("dp_percentagevalue2");
        const ScoreOptionC: Xrm.Attributes.OptionSetAttribute | null = FORM_CONTEXT.getAttribute("dp_pickascorefirmwide");
        const PercentageOptionC: Xrm.Attributes.OptionSetAttribute | null = FORM_CONTEXT.getAttribute("dp_percentagevaluefirmwide");
        
        // Define Scoring & Percentages 
        const scoreMap: { [Score: number]: number } = {
            778180000: 1,
            778180001: 2,
            778180002: 3,
            778180003: 4,
            778180004: 5
        };
        const percentageMap: { [Percentage: number]: number } = {
            778180000: 0.10,
            778180001: 0.20,
            778180002: 0.30,
            778180003: 0.40,
            778180004: 0.50
        };

        // 初始化变量默认值,避免NaN
        let SectionAScore = 0, SectionAPercentage = 0, SectionBScore = 0, SectionBPercentage = 0, SectionCScore = 0, SectionCPercentage = 0;
        
        // Section A Score & Percentages 
        if (ScoreOptionA != null && PercentageOptionA != null) {
            const scoreValueA = ScoreOptionA.getValue();
            const percentageValueA = PercentageOptionA.getValue();
            // 额外判断返回值不为null,确保索引是number类型
            if (scoreValueA !== null && percentageValueA !== null) {
                SectionAScore = scoreMap[scoreValueA];
                SectionAPercentage = percentageMap[percentageValueA];
            }
        }
        
        //Section B Set Score & Percentages
        if (ScoreOptionB != null && PercentageOptionB != null) {
            const ScoreValueB = ScoreOptionB.getValue();
            const valuePercentageB = PercentageOptionB.getValue();
            if (ScoreValueB !== null && valuePercentageB !== null) {
                SectionBScore = scoreMap[ScoreValueB];
                SectionBPercentage = percentageMap[valuePercentageB];
            }
        }
        
        // Section C Score & Percentages 
        if (ScoreOptionC != null && PercentageOptionC != null) {
            const ScoreValueC = ScoreOptionC.getValue();
            const valuePercentageC = PercentageOptionC.getValue();
            if (ScoreValueC !== null && valuePercentageC !== null) {
                SectionCScore = scoreMap[ScoreValueC];
                SectionCPercentage = percentageMap[valuePercentageC];
            }
        }
        
        // Calculations
        const Section1Score = SectionAScore * SectionAPercentage;
        const Section2Score = SectionBScore * SectionBPercentage;
        const Section3Score = SectionCScore * SectionCPercentage;
        const averagescore = Section1Score + Section2Score + Section3Score;
        
        // Set Average Score Value:先检查属性是否存在
        const averageAttr = FORM_CONTEXT.getAttribute("dp_decimal");
        if (averageAttr) {
            averageAttr.setValue(averagescore);
        }
    } catch (error) {
        console.log(`exampleFunction error`, error);
        HELPERS.displayErrorMessage(error);
    } finally {
        console.log(`exampleFunction finally`);
    }
}

关键修复点

  • 修正类型声明:给所有OptionSetAttribute变量添加| null,匹配getAttribute()的实际返回值类型。
  • 正确使用getValue()结果:将getValue()的返回值赋值给变量,用该变量作为索引访问映射表,而非直接使用OptionSetAttribute对象。
  • 增加null判断:在对象非空的基础上,额外检查getValue()的结果是否为null,确保索引为有效number类型。
  • 初始化变量默认值:给分数、百分比变量设置初始值0,避免计算出现NaN。
  • 修正映射表误用:修复Section A中错误的映射表和变量引用问题。
  • 安全设置属性值:获取目标属性后先判断是否存在,再调用setValue()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:54:52