TypeScript中type与interface扩展差异及数据库类型定义报错解决方案问询
映射类型报错修复
TS不允许在同一个对象类型声明里同时写固定属性和映射语法,你可以用交叉类型实现带id的通用扩展类型,语法更简洁,还能自动同步基础类型的属性变更:
// 基础业务类型 interface Employee { name: string } // 通用数据库对象泛型 type IDatabaseObject<T> = T & { id: string } // 直接生成带id的Employee类型,不需要手动重复写属性 type EmployeeDb = IDatabaseObject<Employee>
修复后就不会再出现A computed property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)的报错。
存储类类型转换报错修复
报错的核心原因是双泛型设计的类型漏洞:TS无法保证你声明的OutputDataType一定是InputDataType加id的结构,比如实例化时如果给OutputDataType额外加了必填的createTime字段,你返回的对象就不符合类型要求,因此TS会阻止直接类型转换。
推荐修复方案:简化为单泛型设计
直接由输入类型推导输出类型,完全消除类型不匹配的风险:
class DbAsyncStorageTemplate<InputDataType> { async addEntry(object: InputDataType): Promise<IDatabaseObject<InputDataType>> { const id: string = generateUuid() const dbObject = { id, ...object } // 注意原代码存储的是不带id的输入对象,如果需要存储完整数据请改为dbObject await AsyncStorage.setItem(id, JSON.stringify(dbObject)) return dbObject } }
使用时只需要传入基础业务类型即可,返回值会自动带上id类型:
const employeeStorage = new DbAsyncStorageTemplate<Employee>() // 返回值类型为 Promise<EmployeeDb> const newEmployee = await employeeStorage.addEntry({ name: "张三" })
可选修复方案:保留双泛型
如果业务场景确实需要自定义输出类型,可以按照TS提示先转unknown再转目标类型,前提是你能保证业务逻辑返回的对象符合OutputDataType的所有要求:
return dbObject as unknown as OutputDataType
内容的提问来源于stack exchange,提问作者Armen Babakanian
相关产品推荐
相关产品推荐

