TypeScript如何实现函数一个参数的类型依赖另一参数的取值?
问题根因
TypeScript 目前不支持对未实例化的泛型参数做关联窄化:你在函数内部对action参数做值判断时,TS 只会窄化action本身的类型,不会同步推导泛型参数K的实际类型,因此依赖K的LayoutType<K>始终处于未解析状态,无法根据分支自动匹配对应的类型,才会出现两个分支都识别不到h属性的问题。
解决方案
推荐使用可辨识联合元组重写函数参数定义,TS 对联合类型的窄化能力可以完美匹配你的需求:
export interface LaneLayout { i: number; x: number; y: number; w: number; h: number; lane_content: string; project_id: number; } export type Action = "modify" | "create"; export type ModifiedLaneLayout = Omit< LaneLayout, "project_id" | "lane_content" >; export type CreatedLaneLayout = Pick<LaneLayout, "x" | "y">; // 定义参数的可辨识联合元组 type ModifyBoxParams = | [action: "modify", layout: ModifiedLaneLayout] | [action: "create", layout: CreatedLaneLayout] export function modifyBox(...[action, layout]: ModifyBoxParams): void { if (action === "modify") { layout.h; // 可正常访问h属性,类型正确 } else { layout.h // 此处TS会抛出属性不存在的错误,符合预期 } }
如果需要保留原有泛型写法,也可以在分支内手动添加类型断言使用,但是类型安全性略低于上述联合元组方案:
export type LayoutType<T extends Action> = T extends "modify" ? ModifiedLaneLayout : T extends "create" ? CreatedLaneLayout : never; export function modifyBox<K extends Action>( action: K, layout: LayoutType<K> ): void { if (action === "modify") { (layout as ModifiedLaneLayout).h; // 手动断言后可正常访问 } else { (layout as CreatedLaneLayout).x // 类型正常 } }
内容的提问来源于stack exchange,提问作者Tom van Nes
相关产品推荐
相关产品推荐

