参数已根据未定义进行检查,但编译器仍会发出有关 TS2532 的警告

Parameter is checked against undefined but compiler still warns about TS2532

我在一个项目中使用 DynamoDb 从中获取数据。
我们的一个查询使用 :id 参数来过滤记录:

async getJobsFromDatabaseById(id: string): Promise<Job[]> {
  const idParameter = ":id";
  const parameters: AWS.DynamoDB.DocumentClient.QueryInput = {
    //It has been already initialized inside ctor
    /* eslint-disable  @typescript-eslint/no-non-null-assertion */
    TableName: this.tableName!,
    KeyConditionExpression: `Id = ${idParameter}`
  };

  parameters.ExpressionAttributeValues = {};
  parameters.ExpressionAttributeValues[idParameter] = id;

  const result = await this.client().query(parameters).promise();
  return this.mapDbRecordsToJobs(result.Items);
}

client() 方法 returns 与 AWS.DynamoDB.DocumentClient 实例。

在单元测试中,我通过以下方式模拟查询:

import * as AWSMock from "jest-aws-sdk-mock";

...
//This type alias is introduced to avoid the usage of `Object`
/* eslint-disable @typescript-eslint/no-unused-vars*/
type DatabaseRecord = Record<string, unknown>;
...

const idParameter = ":id"; //I know this is tight-coupling to implementation
const MockQuery = (records: Array<DatabaseRecord>): void => {
  AWSMock.mock(
    "DynamoDB.DocumentClient",
    "query",
    (
      _parameters: AWS.DynamoDB.DocumentClient.QueryInput,
      callback: (
        error: AWS.AWSError | undefined,
        data: AWS.DynamoDB.DocumentClient.QueryOutput
      ) => void
    ) => {
      let filteredRecords: DatabaseRecord[] = records;
      if (
        _parameters.ExpressionAttributeValues &&
        _parameters.ExpressionAttributeValues[idParameter]
      ) {
        /* eslint-disable  @typescript-eslint/no-non-null-assertion */
        filteredRecords = records.filter(
          record => record.Id === _parameters.ExpressionAttributeValues![idParameter]
        );
      }

      const output: AWS.DynamoDB.DocumentClient.QueryOutput = {
        Items: filteredRecords
      };
      callback(undefined, output);
    }
  );
};

我的问题是我必须使用非空断言运算符,即使我根据 undefined.
检查了对象 这很好用:

if (
  _parameters.ExpressionAttributeValues &&
  _parameters.ExpressionAttributeValues[idParameter]
) {
  /* eslint-disable  @typescript-eslint/no-non-null-assertion */
  filteredRecords = records.filter(
    record => record.Id === _parameters.ExpressionAttributeValues![idParameter]
  );
}

但这给了我 TS2532 错误对象可能是 undefined:

if (
  _parameters.ExpressionAttributeValues &&
  _parameters.ExpressionAttributeValues[idParameter]
) {
  filteredRecords = records.filter(
    record => record.Id === _parameters.ExpressionAttributeValues[idParameter]
  );
}

我尝试在不依赖 DynamoDb 的情况下重现同样的问题:

interface Test {
    Parameters? : {[key: string]: any}
}

function GetData() : Test {
    return {
    Parameters: {
        "x": 1,
        "y": 2
    }
   };
}

function PrintData(data: Test){
    if(data.Parameters)
    {
        console.log(data.Parameters["x"])
    }
}

var data = GetData();
PrintData(data);

它确实可以正常工作。

我必须更改什么才能避免使用非空断言运算符?


更新Optional chaining

即使可选链接不会引发 eslint 警告,它仍然感觉很奇怪:

if (
  _parameters.ExpressionAttributeValues &&
  _parameters.ExpressionAttributeValues[idParameter]
) {
  filteredRecords = records.filter(
    record => record.Id === _parameters.ExpressionAttributeValues?.[idParameter]
  );
}

我们最终使用了这样的可选链接:

const idParamValue = _parameters.ExpressionAttributeValues?.[idParameter];

if (idParamValue) {
  filteredRecords = records.filter(record => record.Id === idParamValue);
}