TypeScript自定义类型属性设默认值的类型报错及类属性类型问题
TypeScript自定义类型默认值设置的类型问题及解决方案
问题描述
尝试为自定义类型的未定义属性设置默认值,编写代码后遇到类型错误,后续在类场景中又出现属性类型被推断为any的问题。
初始代码与错误
// 包含所有可选属性的自定义类型 type MyType = { // 示例属性: str?: string } // 假设有成百上千个属性,无法逐个赋值,因此创建默认值对象 const defaultValuesForMyType: MyType = { str: "hello world!" } // 接收字符串执行操作的函数(假设是无法修改的外部API函数) function doThingsWithString(str: string): void { // 示例操作: console.log(str); } // 接收自定义类型对象的驱动函数 function driver(inputObject: MyType) { const finalObject: MyType = { ...defaultValuesForMyType, ...inputObject }; doThingsWithString(finalObject.str); }
VS Code提示错误:
doThingsWithString(finalObject.str); ^~~~~~~~~~~~~~^
错误信息:
Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. ts(2345) const finalObject: { str?: string | undefined; }
类场景的后续问题
调整代码后类型错误消失,但类中属性propObject被推断为any:
// 包含所有可选属性的自定义类型 type MyType = { // 示例属性: str?: string } // 假设有成百上千个属性,无法逐个赋值,因此创建默认值对象 const defaultValuesForMyType = { str: "hello world!" } // 接收字符串执行操作的函数(假设是无法修改的外部API函数) function doThingsWithString(str: string): void { // 示例操作: console.log(str); } class TestClass { propObject; driver(inputObject: MyType) { this.propObject = { ...defaultValuesForMyType, ...inputObject }; doThingsWithString(this.propObject.str); } }
问题根源
- 初始错误:为
defaultValuesForMyType手动标注MyType类型,导致TypeScript仍将其属性视为可选类型,即使已赋值具体值。合并后的对象类型继承了MyType的可选属性定义,因此finalObject.str被推断为string | undefined。 - 类场景问题:未显式标注
propObject的类型,TypeScript默认将其推断为any。
解决方案
1. 解决初始类型错误
移除defaultValuesForMyType的手动类型标注,让TypeScript自动推断其属性为必选,再通过工具类型生成合并后的安全类型:
type MyType = { str?: string } // 不手动标注类型,让TS自动推断所有属性为必选 const defaultValuesForMyType = { str: "hello world!" } // 生成合并后的类型:覆盖MyType的可选属性为必选 type MergedMyType = Omit<MyType, keyof typeof defaultValuesForMyType> & typeof defaultValuesForMyType; function doThingsWithString(str: string): void { console.log(str); } function driver(inputObject: MyType) { const finalObject = { ...defaultValuesForMyType, ...inputObject } as MergedMyType; doThingsWithString(finalObject.str); // 此时str为string类型,无错误 }
2. 解决类中propObject的any类型问题
显式为propObject标注合并后的类型:
type MyType = { str?: string } const defaultValuesForMyType = { str: "hello world!" } type MergedMyType = Omit<MyType, keyof typeof defaultValuesForMyType> & typeof defaultValuesForMyType; function doThingsWithString(str: string): void { console.log(str); } class TestClass { // 显式标注类型为MergedMyType propObject: MergedMyType; driver(inputObject: MyType) { this.propObject = { ...defaultValuesForMyType, ...inputObject } as MergedMyType; doThingsWithString(this.propObject.str); // 类型安全,无错误 } }
简洁替代方案(利用返回值类型推断)
通过函数返回值的自动推断来简化类型定义:
type MyType = { str?: string } const defaultValuesForMyType = { str: "hello world!" } function doThingsWithString(str: string): void { console.log(str); } // 合并函数,让TS自动推断返回类型 function mergeDefaults(input: MyType) { return { ...defaultValuesForMyType, ...input }; } class TestClass { // 使用mergeDefaults的返回类型作为propObject的类型 propObject: ReturnType<typeof mergeDefaults>; driver(inputObject: MyType) { this.propObject = mergeDefaults(inputObject); doThingsWithString(this.propObject.str); } }
内容的提问来源于stack exchange,提问作者star_huey
相关产品推荐
相关产品推荐

