使用AWS DataStore.query时,Linter类型提示与实际返回值不符
AWS Amplify DataStore AWSJSON类型提示与运行时类型冲突的解决方案
当使用Amplify DataStore查询AWSJSON类型字段时,Linter提示的类型(string | undefined | null)与运行时实际返回的解析后对象存在冲突,导致代码逻辑错误或运行时异常。
示例场景
schema.graphql
type Card @model @auth(rules: [{ allow: private }]) { id: ID! input: AWSJSON }
问题代码
const originalCard = await DataStore.query(Card, cardid); // Linter提示originalCard.input为string | undefined | null if(!originalCard.input) return; await DataStore.save( Card.copyOf(originalCard, (updated) => { // 错误:因类型提示误判,手动调用JSON.stringify,导致运行时数据被重复序列化 updated.input = JSON.stringify(originalCard.input); }) );
运行时会报错,因为originalCard.input实际是DataStore自动解析后的JS对象,而非字符串。
问题根源
Amplify代码生成工具默认将AWSJSON类型生成为string | null | undefined(对应DynamoDB存储的原始JSON字符串),但DataStore在查询时会自动将该字符串解析为JS对象,导致类型提示与实际运行值不一致。
操作纠正
无需手动调用JSON.stringify处理AWSJSON字段——DataStore会自动完成对象的序列化(存入时)和反序列化(查询时)。代码中额外的序列化操作反而会导致数据被重复编码,引发异常。
最优解决方案
1. 自定义类型别名(持久化方案)
通过自定义类型覆盖Amplify生成的类型,避免每次执行amplify codegen models时被覆盖:
import { Card as GeneratedCard, DataStore } from './src/models'; // 修正AWSJSON字段的类型定义 type Card = Omit<GeneratedCard, 'input'> & { input?: Record<string, any> | null; }; // 查询时断言为修正后的类型 const originalCard = (await DataStore.query(GeneratedCard, cardid)) as Card; if (!originalCard.input) return; // 直接保存原对象,DataStore会自动处理序列化 await DataStore.save( GeneratedCard.copyOf(originalCard as GeneratedCard, (updated) => { updated.input = originalCard.input; }) );
2. 局部类型断言(临时方案)
如果仅需处理单个场景,可使用更简洁的类型断言:
const originalCard = await DataStore.query(Card, cardid); if(!originalCard.input) return; await DataStore.save( Card.copyOf(originalCard, (updated) => { // 明确断言input为对象类型 updated.input = originalCard.input as Record<string, any>; }) );
3. 反馈官方修复根本问题
这是Amplify代码生成工具的已知问题,你可以在AWS Amplify的GitHub仓库提交Issue,说明AWSJSON类型在DataStore场景下的类型生成错误,推动官方修复。
内容的提问来源于stack exchange,提问作者JimmyTheCode
相关产品推荐
相关产品推荐

