TypeScript报错:Type 'null'无法赋值给SetStateAction<string>的解决方法
修复TypeScript中Firebase登录的类型错误
问题场景
将JavaScript版的React Firebase登录代码转为TypeScript后,VS Code抛出了类型不匹配的错误,源代码如下:
import React, { useEffect, useState } from 'react'; import './output.css'; // Adjust path if necessary import {auth, provider} from './config' ; import { signInWithPopup } from 'firebase/auth'; import Home from './Home'; function SignIn(){ const [value,setValue] = useState('') const handleClick = () => { signInWithPopup(auth, provider).then((data) => { setValue(data.user.email) localStorage.setItem("email", data.user.email) }) } useEffect(() => { setValue(localStorage.getItem('email')) }) return ( <div> {value?<Home/>: <button onClick={handleClick} className='px-2 bg-blue-600 text-white hover:bg-blue-900 pt-2 pb-2 pl-3 pr-3 rounded-md'>Sign in with Google</button> } </div> ); } export default SignIn;
错误信息
- 第12行
data.user.email:类型string | null无法赋值给类型SetStateAction<string>,Typenull无法赋值给类型SetStateAction<string>。ts(2345) - 第12行
data.user.email:类型string | null无法赋值给类型string,Typenull无法赋值给类型string。ts(2345) - 第18行
localStorage.getItem('email'):类型string | null无法赋值给类型SetStateAction<string>,Typenull无法赋值给类型SetStateAction<string>。ts(2345)
修复方案
这些错误的核心原因是TypeScript的严格类型检查:Firebase的User.email和localStorage.getItem()都可能返回null,但你的value状态被初始化为空字符串(类型为string),不接受null值。可以通过以下方式修复:
1. 处理空值并确保类型匹配
使用空值合并运算符(??)为可能为null的值提供默认空字符串,同时修正useEffect的依赖数组避免无限循环:
const handleClick = () => { signInWithPopup(auth, provider).then((data) => { // 给可能为null的email设置默认空字符串 const userEmail = data.user.email ?? ''; setValue(userEmail); localStorage.setItem("email", userEmail); }) } useEffect(() => { // 处理localStorage返回的null值 setValue(localStorage.getItem('email') ?? ''); }, []) // 添加空依赖数组,仅在组件挂载时执行一次
2. 调整状态类型(可选)
如果希望状态允许null值,可以显式声明状态类型为string | null,这样setValue能直接接受null:
const [value, setValue] = useState<string | null>('');
这种方式更贴合“未登录时无邮箱”的实际场景,后续判断逻辑不需要额外调整。
完整修正后的代码
import React, { useEffect, useState } from 'react'; import './output.css'; // Adjust path if necessary import { auth, provider } from './config'; import { signInWithPopup } from 'firebase/auth'; import Home from './Home'; function SignIn() { const [value, setValue] = useState<string>(''); const handleClick = () => { signInWithPopup(auth, provider).then((data) => { const userEmail = data.user.email ?? ''; setValue(userEmail); localStorage.setItem("email", userEmail); }); }; useEffect(() => { setValue(localStorage.getItem('email') ?? ''); }, []); return ( <div> {value ? <Home /> : ( <button onClick={handleClick} className='px-2 bg-blue-600 text-white hover:bg-blue-900 pt-2 pb-2 pl-3 pr-3 rounded-md' > Sign in with Google </button> )} </div> ); } export default SignIn;
额外说明
如果确定Google登录后的用户一定有邮箱,也可以用非空断言运算符(!)强制告知TypeScript值不为null,但这种方式不推荐——若出现异常场景(比如用户账号无邮箱)会引发运行时错误:
setValue(data.user.email!) localStorage.setItem("email", data.user.email!)
内容的提问来源于stack exchange,提问作者Jahin Ahnaf
相关产品推荐
相关产品推荐

