Angular Strict模式下TypeScript类型赋值报错原因与解决方案
TypeScript TS2322错误分析与解决
类型与函数定义
export interface LanguageEditInfoDto { canEdit: boolean; label: string; useDudenLang: boolean; } export type UILanguageEditInfoDto = LanguageEditInfoDto & { isFormValid: boolean; }; function setLanguages(languages: Record<string, LanguageEditInfoDto>) { const langState: Record<string, UILanguageEditInfoDto> = {}; for (const langCode in languages) { langState[langCode] = { isFormValid: true, ...languages[langCode], }; } }
错误信息
TS2322: Type
{ canEdit?: boolean | undefined; label?: string | undefined; useDudenLang?: boolean | undefined; isFormValid: true; }is not assignable to typeUILanguageEditInfoDto
Type{ canEdit?: boolean | undefined; label?: string | undefined; useDudenLang?: boolean | undefined; isFormValid: true; }is not assignable to typeLanguageEditInfoDto
错误原因
问题出在for...in循环中对languages[langCode]的类型推断:
Record<string, LanguageEditInfoDto>的索引签名规定,任意字符串键都可能对应值或undefined,TypeScript不会因为langCode来自for...in循环就自动推断languages[langCode]一定存在,因此它的类型被判定为LanguageEditInfoDto | undefined。- 当展开一个可能为
undefined的对象时,TypeScript会将原接口的所有属性标记为可选(因为如果原对象是undefined,展开后不会包含这些属性),最终合并后的对象类型变成{isFormValid: true} & Partial<LanguageEditInfoDto>,与要求的UILanguageEditInfoDto(必填属性+isFormValid)类型不兼容。
解决方法
有以下几种可行的解决方式:
1. 使用非空断言操作符!
明确告诉TypeScriptlanguages[langCode]一定存在:
function setLanguages(languages: Record<string, LanguageEditInfoDto>) { const langState: Record<string, UILanguageEditInfoDto> = {}; for (const langCode in languages) { langState[langCode] = { isFormValid: true, ...languages[langCode]!, }; } }
2. 类型断言
直接断言languages[langCode]的类型为LanguageEditInfoDto:
function setLanguages(languages: Record<string, LanguageEditInfoDto>) { const langState: Record<string, UILanguageEditInfoDto> = {}; for (const langCode in languages) { langState[langCode] = { isFormValid: true, ...languages[langCode] as LanguageEditInfoDto, }; } }
3. 改用Object.entries遍历
通过键值对遍历,直接获取明确的LanguageEditInfoDto类型值:
function setLanguages(languages: Record<string, LanguageEditInfoDto>) { const langState: Record<string, UILanguageEditInfoDto> = {}; for (const [langCode, lang] of Object.entries(languages)) { langState[langCode] = { isFormValid: true, ...lang, }; } }
4. 添加空值检查(冗余但安全)
通过条件判断缩小类型范围,虽然逻辑上不会触发,但能让TypeScript正确推断类型:
function setLanguages(languages: Record<string, LanguageEditInfoDto>) { const langState: Record<string, UILanguageEditInfoDto> = {}; for (const langCode in languages) { const lang = languages[langCode]; if (!lang) continue; langState[langCode] = { isFormValid: true, ...lang, }; } }
内容的提问来源于stack exchange,提问作者LeO
相关产品推荐
相关产品推荐

