TypeScript中Array.find()参数类型指定失败的原因求解
TypeScript Array.find() 类型推断问题解析
定义的接口类型
export declare interface OrganisationInterface { documents?: { [documentType: OrganisationDocumentTypesList]: { // enum id: string; name: string; src?: string; } }; }
代码尝试及报错
const organisation = { ...<OrganisationInterface>organisationSnap.data(), id: organisationId } // 尝试1 - 让TypeScript推断'record'变量的类型 // TS报错:'record'的类型为'unknown' const documentRecord = Object.values(organisation?.documents ?? {}).find((record) => record.id! === fileId) // 尝试2 - 强制转换'record'类型 // TS报错:没有匹配的重载调用 const documentRecord = Object.values(organisation?.documents ?? {}).find((<OrganisationInterface['documents']>record) => record.id! === fileId) // 尝试3 - 在find方法右侧强制转换'record'变量 // TS报错 - 'documents'可能未定义 const documentRecord = Object.values(organisation?.documents ?? {}).find((record) => (<OrganisationInterface['documents']>record).id! === fileId) // 尝试4 - 将'documents'子对象改为必填项 // TS报错 - 类型'{}'上不存在属性'id' const documentRecord = Object.values(organisation?.documents ?? {}).find((record) => (<Required<OrganisationInterface>['documents']>record).id! === fileId)
问题
为何TypeScript不允许我为Array.find()函数返回的'record'变量指定类型?
报错原因
- 类型推断失效:
organisation?.documents ?? {}中,当documents不存在时会返回空对象{},TypeScript无法推断空对象的结构,导致Object.values()返回的数组元素类型为unknown,find回调里的record自然是unknown,访问id会触发报错。 - 类型转换方向错误:你尝试将
record转为OrganisationInterface['documents'],但这是整个文档索引对象的类型(键为枚举、值为文档项的对象),而Object.values()取出的是这个对象里的单个文档项,并非整个索引对象,类型不匹配导致报错。
解决方案
方法一:提取文档项类型复用
先从接口中提取单个文档项的类型,后续使用更清晰:
// 从OrganisationInterface中提取文档项类型 type OrganisationDocument = OrganisationInterface['documents'][keyof OrganisationInterface['documents']]; // 推荐用as语法做类型断言(TSX文件中尖括号会被识别为JSX标签,避免冲突) const organisation = { ...organisationSnap.data() as OrganisationInterface, id: organisationId }; // 处理documents,兜底空对象并指定类型 const documents = organisation.documents ?? {}; const documentRecord = Object.values(documents as Record<string, OrganisationDocument>).find(record => record.id === fileId);
方法二:直接断言数组类型
如果不想单独定义类型,可直接给Object.values()的结果指定数组类型:
const organisation = { ...organisationSnap.data() as OrganisationInterface, id: organisationId }; const documentRecord = Object.values(organisation.documents ?? {}) as Array<{ id: string; name: string; src?: string; }>; const targetDocument = documentRecord.find(doc => doc.id === fileId);
关键要点
Object.values()作用于documents时,返回的是文档项的数组,类型要对应单个文档项,而非整个索引对象。- 优先给
Object.values()的结果指定正确类型,TypeScript会自动推断find回调中record的类型,无需在回调内强行转换。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

