TypeScript中DynamoDB get操作返回类型定义及类型报错解决
首先先提个小语法问题:你写的let resItem: Schema resItem = ...是错误的,应该改成let resItem: Schema = ...,不过这不是导致类型报错的核心原因——真正的问题是你误解了DynamoDB Get操作的返回结构。
dynamoClient.get().promise()返回的并不是你定义的Schema类型对象,而是AWS SDK的PromiseResult<GetItemOutput, AWSError>结构:这个结构里的Item字段才是存储你实际数据的地方,而且它的格式是DynamoDB特有的AttributeValue(比如字符串会是{ S: "xxx" }这种嵌套形式),和你的Schema类型完全不匹配,所以TypeScript会抛出类型错误。
下面是完整的解决方案:
1. 先处理DynamoDB数据格式转换
AWS SDK提供了工具来把DynamoDB的AttributeValue格式转换成普通JS对象,根据你使用的SDK版本选择对应方法:
如果你用的是AWS SDK v3:
先安装转换工具包:
npm install @aws-sdk/util-dynamodb
然后导入工具:
import { unmarshall } from "@aws-sdk/util-dynamodb";
如果你用的是AWS SDK v2:
直接使用SDK内置的转换器:
import AWS from "aws-sdk"; const { unmarshall } = AWS.DynamoDB.Converter;
2. 正确获取并类型化返回结果
修改你的代码,先获取完整的响应,取出Item后转换格式,再指定为你的Schema类型:
// 执行get操作,获取完整响应 const getResult = await dynamoClient.get({ TableName, Key: { uuid: { S: request.body.uuid } } // 注意:原生DynamoDB client需要用AttributeValue格式,若用DocumentClient则直接传字符串 }).promise(); // 处理Item:存在则转换格式并指定类型,不存在则设为null let resItem: Schema | null = null; if (getResult.Item) { resItem = unmarshall(getResult.Item) as Schema; }
额外提示:如果你使用的是
DocumentClient(不管v2还是v3),它会自动帮你做格式转换,这时候Item已经是普通JS对象,你可以直接断言类型:const getResult = await dynamoClient.get({ TableName, Key: { uuid: request.body.uuid } }).promise(); const resItem = getResult.Item as Schema | null;
3. 更严格的类型安全(可选)
如果不想用as类型断言,想要更严谨的类型检查,可以写一个类型守卫函数:
function isSchema(item: unknown): item is Schema { return ( typeof item === "object" && item !== null && "uuid" in item && typeof (item as Schema).uuid === "string" && "topics" in item && Array.isArray((item as Schema).topics) && "phoneNumber" in item && typeof (item as Schema).phoneNumber === "string" && "timezone" in item && typeof (item as Schema).timezone === "string" ); } // 使用类型守卫 if (getResult.Item) { const parsedItem = unmarshall(getResult.Item); if (isSchema(parsedItem)) { resItem = parsedItem; } else { // 处理类型不匹配的情况,比如抛出错误或记录日志 throw new Error("返回的数据不符合Schema类型定义"); } }
这样就能确保resItem的类型完全符合你的Schema定义,不会再出现类型错误啦!
内容的提问来源于stack exchange,提问作者Shamoon

