如何在子作用域中使用类型守卫定义的Props而无需重复定义类型
解决React/TypeScript联合类型Props解构后变量隐式any问题
方案1:使用带判别式的状态对象(推荐)
通过立即执行函数生成带有类型判别式的状态对象,让TypeScript自动推断字段类型,无需手动声明:
type WrongInfoProps = ( | WrongInfoCompanyProps | WrongInfoPersonProps | WrongInfoBranchProps ) & WrongInfoCallbackProps; interface WrongInfoCallbackProps { onClose: (isModalOpen?: boolean) => void; } interface WrongInfoCompanyProps { companyId: number; } interface WrongInfoBranchProps { branchId: number; branchName: string; companyId: number; parentName: string; } interface WrongInfoPersonProps { employmentId: number; execId: number; companyName: string; } export default function App(props: WrongInfoProps) { // 用立即执行函数生成带判别式的状态对象 const state = (() => { if ("branchId" in props) { const { branchId, companyId, branchName, parentName } = props; return { type: "branch", branchId, companyId, branchName, parentName }; } else if ("companyId" in props) { const { companyId } = props; return { type: "company", companyId }; } else { const { execId, employmentId, companyName } = props; return { type: "person", execId, employmentId, companyName }; } })(); const renderCompany = () => { // 通过判别式缩小类型范围,TypeScript自动推断companyId为number if (state.type === "branch" || state.type === "company") { return <div>{state.companyId}</div>; } return null; // 处理无companyId的场景 }; return ( <div className="App"> <h1>{renderCompany()}</h1> <div>{state.type !== "person" && state.companyId}</div> </div> ); }
优势:
- 完全利用TypeScript类型推断,无需手动声明变量类型
- 通过判别式
type明确区分不同Props类型,避免类型歧义 - 变量作用域清晰,无隐式any问题
方案2:复用已有Props类型声明变量
如果不想大幅改动现有代码,可从已有的Props接口中提取字段类型,避免重复定义:
// ... 类型定义部分不变 export default function App(props: WrongInfoProps) { // 从已有接口提取类型,避免重复写number let companyId: WrongInfoCompanyProps["companyId"] | undefined; let branchId: WrongInfoBranchProps["branchId"] | undefined; let branchName: WrongInfoBranchProps["branchName"] | undefined; let parentName: WrongInfoBranchProps["parentName"] | undefined; let execId: WrongInfoPersonProps["execId"] | undefined; let employmentId: WrongInfoPersonProps["employmentId"] | undefined; let companyName: WrongInfoPersonProps["companyName"] | undefined; if ("branchId" in props) { ({ branchId, companyId, branchName, parentName } = props); } else if ("companyId" in props) { ({ companyId } = props); } else if ("execId" in props) { ({ execId, employmentId, companyName } = props); } const renderCompany = () => { // 判断变量是否存在,TypeScript自动缩小类型范围 if (companyId !== undefined) { return <div>{companyId}</div>; } return null; }; return ( <div className="App"> <h1>{renderCompany()}</h1> <div>{companyId}</div> </div> ); }
通过WrongInfoCompanyProps["companyId"]复用已有类型定义,既避免重复写number,又让TypeScript明确变量类型,解决隐式any问题。
方案3:直接在函数内做类型守卫
如果仅需在特定函数中使用companyId,可直接在函数内对props做类型守卫,无需提前解构:
// ... 类型定义部分不变 export default function App(props: WrongInfoProps) { const renderCompany = () => { // 直接在函数内判断props类型,TypeScript自动推断companyId类型 if ("companyId" in props) { return <div>{props.companyId}</div>; } return null; }; return ( <div className="App"> <h1>{renderCompany()}</h1> <div>{("companyId" in props) && props.companyId}</div> </div> ); }
该方案最简洁,适合无需提前解构大量字段的场景,直接利用in操作符做类型守卫即可。
内容的提问来源于stack exchange,提问作者mysl
相关产品推荐
相关产品推荐

