TypeScript报错TS2339:类型UserMetadata不存在属性'b'求助
问题原因与解决方法
嗨,我来帮你搞清楚这个问题!
为什么会报错?
你遇到的是TypeScript静态类型检查和Firebase内部实现之间的冲突:
- 虽然在运行时,
userCredential.user.metadata确实有b这个属性(它是Firebase用来存储创建时间的内部私有字段),但TypeScript的类型定义文件里,UserMetadata类型并没有声明b这个属性——TypeScript只认官方定义的公开API字段,不认这些未文档化的内部字段。 - 而
console.log能正常输出是因为JavaScript是动态类型语言,运行时不管类型定义,只要实际存在这个属性就能访问到,但TS编译阶段会严格校验类型匹配,所以抛出了错误。
解决方法(推荐优先用第一种)
1. 使用Firebase官方提供的公开API字段(最稳妥)
Firebase的UserMetadata类型其实已经提供了公开的creationTime和lastSignInTime属性,它们是类型定义里合法的字段,而且是文档化的稳定API。你需要做的只是把字符串格式的时间转成数字时间戳:
login(email: string, password: string): Promise<any> { return this.afAuth.signInWithEmailAndPassword(email, password) .then(userCredential => { // 使用公开的creationTime,转成数字时间戳 const creationTime: number = Date.parse(userCredential.user.metadata.creationTime); console.log('creationTime', creationTime); this.handleAuthentication( userCredential.user.email, userCredential.user.uid, 'xxx', creationTime ); }) .catch(error => { console.log(error); }); }
这种方法不会依赖Firebase的内部实现,就算Firebase更新代码,你的代码也不会突然失效。
2. 类型断言绕过TS检查(不推荐,仅临时应急)
如果你非要访问那个内部的b字段(强烈不建议,因为内部字段随时可能被修改),可以用类型断言告诉TS“我知道这个属性存在”:
// 用as any绕过类型检查 const creationTime: number = (userCredential.user.metadata as any).b;
但要注意,这种写法是不安全的——如果Firebase后续把b改成其他名字,你的代码就会出错,而且没有编译警告。
3. 扩展UserMetadata类型定义(可选,需谨慎)
如果你长期需要使用这个内部字段,可以在项目里扩展UserMetadata的类型定义:
// 在项目的.d.ts文件里添加类型扩展 declare module 'firebase/auth' { interface UserMetadata { b?: number; } }
不过同样要承担内部字段变动的风险,除非你确定这个字段不会被修改。
内容的提问来源于stack exchange,提问作者Jakub Nam
相关产品推荐
相关产品推荐

