TypeScript中能否在不重复代码的前提下进行类型断言?
TypeScript类型断言优化:避免重复代码
我编写了如下代码,能看到当前方案存在的问题:
type Keys = "foo" | "bar"; type Item = { id: string; } type Dated = { date: string; item: Item } function isItem(param: any): param is Item { if (!param) return false; return (param as Item).id !== undefined; } type AddDated = { item: string | Dated; key: Extract<Keys, "foo"> } type AddNonDated = { item: Item; key: Extract<Keys, "bar"> } function addItem(payload: AddDated | AddNonDated) { // Do something } function manageItem(item: AddDated["item"] | AddNonDated["item"], key: Keys) { if (isItem(item) && key === "bar") { addItem({ item: item, key }) } else if (!isItem(item) && key === "foo") { addItem({ item: item, key }) } }
我想了解的是,能否在manageItem函数中实现类型断言,同时避免重复编写使用断言后变量的代码?
解决方案
可以通过以下几种方式实现,既保证类型安全,又避免重复代码:
方案1:抽离合法参数到临时变量
先通过条件判断确认参数组合的合法性,将合法的{item, key}存入临时变量,最后统一调用addItem:
function manageItem(item: AddDated["item"] | AddNonDated["item"], key: Keys) { let validPayload: AddDated | AddNonDated | undefined; if (isItem(item) && key === "bar") { validPayload = { item, key }; } else if (!isItem(item) && key === "foo") { validPayload = { item, key }; } if (validPayload) { addItem(validPayload); } }
方案2:自定义精准类型守卫
创建一个专门的类型守卫,直接验证item和key的组合是否符合addItem的参数要求,之后统一调用:
function isValidAddPayload( item: AddDated["item"] | AddNonDated["item"], key: Keys ): item is (AddNonDated["item"] & { _key: "bar" }) | (AddDated["item"] & { _key: "foo" }) { return (isItem(item) && key === "bar") || (!isItem(item) && key === "foo"); } function manageItem(item: AddDated["item"] | AddNonDated["item"], key: Keys) { if (isValidAddPayload(item, key)) { addItem({ item, key } as AddDated | AddNonDated); } }
方案3:利用条件类型简化断言
直接在条件判断后,通过条件类型推断参数的具体类型,一次性完成断言和调用:
function manageItem(item: AddDated["item"] | AddNonDated["item"], key: Keys) { if ((isItem(item) && key === "bar") || (!isItem(item) && key === "foo")) { addItem({ item, key } as typeof item extends Item ? AddNonDated : AddDated); } }
这些方案的核心都是先确认参数组合的合法性,再将重复的addItem调用逻辑合并到一处,同时通过TypeScript的类型推断或显式断言让编译器认可参数的类型合法性。
内容的提问来源于stack exchange,提问作者LoyalPotato
相关产品推荐
相关产品推荐

