TypeScript不同类型参数疑问:内部函数仅需单一类型是否必用联合类型
不用给内部函数加冗余的联合类型,这样处理更优雅
首先明确说:不需要修改functionInside的参数类型,它既然只需要SchoolClass[],就保持这个精准的类型定义就好——毕竟内部函数的职责应该是处理特定类型的输入,加联合类型反而会模糊它的用途,还带来冗余。
那问题来了,外部函数接收的是ClassesAndSubjects[] | SchoolClass[],怎么安全地调用functionInside呢?答案是在getClassesNumbers内部做类型收窄,告诉TypeScript当前的classes到底是哪一种类型,或者把ClassesAndSubjects[]转换成SchoolClass[]再传入。
常见的类型收窄方式
1. 利用属性判断(如果两个类型有区分属性)
假设SchoolClass有一个className属性,而ClassesAndSubjects没有,你可以这样写:
public getClassesNumbers(classes: ClassesAndSubjects[] | SchoolClass[]) { // 检查数组第一个元素的属性,判断类型 if (classes.length > 0 && 'className' in classes[0]) { // 这里TS会自动识别classes为SchoolClass[] this.functionInside(classes, true); } else { // 处理ClassesAndSubjects[]的情况:转换成SchoolClass[] const schoolClasses = classes.map(item => ({ className: item.subjectName, // 示例转换逻辑,根据实际结构调整 // 补充SchoolClass需要的其他属性 })); this.functionInside(schoolClasses, true); } }
2. 自定义类型守卫函数
如果类型区分需要更复杂的判断,可以写一个类型守卫函数,让TS能明确识别类型:
// 自定义类型守卫,判断传入的数组是否为SchoolClass[] function isSchoolClassArray(arr: ClassesAndSubjects[] | SchoolClass[]): arr is SchoolClass[] { return arr.every(item => typeof item.className === 'string'); } public getClassesNumbers(classes: ClassesAndSubjects[] | SchoolClass[]) { if (isSchoolClassArray(classes)) { // 这里TS确定classes是SchoolClass[],可以直接调用 this.functionInside(classes, true); } else { // 转换ClassesAndSubjects[]为SchoolClass[]后再调用 const convertedClasses = classes.map(item => ({ className: `${item.subject}-${item.grade}`, // 示例转换逻辑 // 其他必要属性 })); this.functionInside(convertedClasses, true); } }
为什么这样做更合理
- 保持内部函数
functionInside的类型精准性,确保它只处理预期的SchoolClass[],避免后续调用时不小心传入错误类型。 - 把类型分支和转换逻辑放在外部函数
getClassesNumbers里,符合“外部处理多样输入,内部专注单一逻辑”的设计思路,代码更清晰易维护。
内容的提问来源于stack exchange,提问作者dooglu
相关产品推荐
相关产品推荐

