TypeScript:函数确保对象属性非空后编辑器仍报未定义错误求助
TypeScript 工具对象传递后的类型推断问题
问题代码
function f1( toolbox: { tool1?: Tool1, tool2?: Tool2, } ) { if (!toolbox.tool1) { toolbox.tool1 = fetchTool1(); } if (!toolbox.tool2) { toolbox.tool2 = fetchTool2(); } // Do something else } function f2( toolbox: { tool1?: Tool1, tool2?: Tool2, } ) { f1(toolbox); // tool1 和 tool2 已被初始化 const x = toolbox.tool1.value // 编辑器报错:tool1 可能为 undefined }
问题描述
我们通过在函数间传递toolbox对象避免重复获取工具,但调用f1后,明明toolbox.tool1和toolbox.tool2已被初始化,编辑器仍报错提示它们可能为undefined。不想用非空断言!或关闭警告,之前尝试让f1返回必填类型的toolbox并重新赋值,也没解决问题。
解决方案
1. 使用类型断言函数(Asserts Function)
直接告诉TypeScript,调用f1后toolbox的所有可选属性都会被初始化:
function f1(toolbox: { tool1?: Tool1; tool2?: Tool2 }): asserts toolbox is { tool1: Tool1; tool2: Tool2 } { if (!toolbox.tool1) { toolbox.tool1 = fetchTool1(); } if (!toolbox.tool2) { toolbox.tool2 = fetchTool2(); } // Do something else } function f2(toolbox: { tool1?: Tool1; tool2?: Tool2 }) { f1(toolbox); // TypeScript 现在识别到 tool1/tool2 已定义 const x = toolbox.tool1.value; // 无报错 }
这是最贴合需求的方案,利用TypeScript的断言函数特性,直接更新类型系统对toolbox的认知。
2. 泛型+类型合并(保留原对象类型)
如果需要保留toolbox原有的额外属性,用泛型跟踪类型:
type PartialToolbox = { tool1?: Tool1; tool2?: Tool2 }; type FullToolbox = Required<PartialToolbox>; function f1<T extends PartialToolbox>(toolbox: T): T & FullToolbox { if (!toolbox.tool1) { toolbox.tool1 = fetchTool1(); } if (!toolbox.tool2) { toolbox.tool2 = fetchTool2(); } return toolbox as T & FullToolbox; } function f2(toolbox: PartialToolbox) { const updatedToolbox = f1(toolbox); const x = updatedToolbox.tool1.value; // 无报错 }
泛型确保返回的类型是原类型与必填工具类型的合并,赋值给新变量后类型推断生效。
3. 拆分类型+返回新对象
如果不希望修改原toolbox对象,可创建新对象并返回必填类型:
type PartialToolbox = { tool1?: Tool1; tool2?: Tool2 }; type FullToolbox = { tool1: Tool1; tool2: Tool2 }; function f1(toolbox: PartialToolbox): FullToolbox { const fullToolbox = { ...toolbox }; if (!fullToolbox.tool1) { fullToolbox.tool1 = fetchTool1(); } if (!fullToolbox.tool2) { fullToolbox.tool2 = fetchTool2(); } // Do something else return fullToolbox; } function f2(toolbox: PartialToolbox) { const fullToolbox = f1(toolbox); const x = fullToolbox.tool1.value; // 无报错 }
通过创建副本并返回明确的必填类型,避免原对象的类型歧义。
内容的提问来源于stack exchange,提问作者Jeffrey Chen
相关产品推荐
相关产品推荐

