开启strictNullChecks后TypeScript对可选链三元表达式报错原因及解法
问题原因与修复方案
为什么TypeScript会报错?
开启strictNullChecks后,TypeScript会严格校验类型的空值情况。你写的text?.length > 0中,text?.length的类型是number | undefined——当text为undefined时,可选链返回undefined。虽然JavaScript运行时undefined > 0会被隐式转换为false,但TypeScript在编译阶段会阻止这种“类型不匹配”的操作:它不允许将number | undefined类型直接与数字做比较,因此抛出'text.length' is possibly 'undefined'的错误。
不用text && text.length > 0的修复方法
1. 结合可选链与空值合并运算符
用??把undefined转换成0,让表达式类型统一为number:
const Button = ({text}: Props) => { const {t, ready} = useTranslation(); const [title, setTitle] = useState(''); useEffect(() => { if (ready) { // 用??将undefined转为0,确保类型是number const btnText = (text?.length ?? 0) > 0 ? text : 'button.default_text'; setTitle(btnText); } }, [ready]); return <button>{t(title)}</button>; }; interface Props { text?: string; }
2. 给可选props设置默认值
直接给text赋空字符串默认值,从根源上消除undefined的可能:
const Button = ({text = ''}: Props) => { // 给text加默认空字符串 const {t, ready} = useTranslation(); const [title, setTitle] = useState(''); useEffect(() => { if (ready) { const btnText = text.length > 0 ? text : 'button.default_text'; setTitle(btnText); } }, [ready]); return <button>{t(title)}</button>; }; interface Props { text?: string; }
此时text的类型始终是string(要么是传入的字符串,要么是空字符串),text.length不会出现undefined。
3. 使用自定义类型守卫
通过类型守卫让TypeScript明确知道分支中text的类型,适合复杂场景:
// 自定义类型守卫,判断值为非空字符串 const isNonEmptyString = (val: unknown): val is string => { return typeof val === 'string' && val.length > 0; }; const Button = ({text}: Props) => { const {t, ready} = useTranslation(); const [title, setTitle] = useState(''); useEffect(() => { if (ready) { const btnText = isNonEmptyString(text) ? text : 'button.default_text'; setTitle(btnText); } }, [ready]); return <button>{t(title)}</button>; }; interface Props { text?: string; }
类型守卫会让TypeScript在isNonEmptyString(text)为true的分支中,推断text是string类型,不会再报错。
内容的提问来源于stack exchange,提问作者Alyona
相关产品推荐
相关产品推荐

