如何在TypeScript中实现基于类静态check方法的返回类型自动收窄?
如何在TypeScript中实现基于类静态check方法的返回类型自动收窄?
我有一批带有static check方法的类,想在wrap方法中找到匹配的类并返回其实例,这种架构非常适合我的OOP需求。我之前在JavaScript中是这么实现的:
class A { static check = arg => typeof arg == "number" constructor(arg) { this.value = arg} log = () => console.log("A/", this.value) } class B { static check = arg => typeof arg == "string" constructor(arg) { this.note = arg } log = () => console.log("B/", this.note) } function wrap(arg, classes) { for (const Class of classes) if (Class.check(arg)) return new Class(arg) } const classes = [A, B] wrap("adaptive", classes).log() wrap(999, classes).log()
最近我想试试用TypeScript来实现,期望wrap函数的调用能自动推断返回类型(毕竟TypeScript就是管类型的),但实际却没做到。我目前能写出的最接近的代码是这样的:
type PayloadA = number type PayloadB = string type PayloadGeneric = PayloadA | PayloadB class A { static check(arg:PayloadGeneric): arg is PayloadA { return typeof arg == "number" } value: number constructor(arg: PayloadA) { this.value = arg} log = () => console.log("A/", this.value) } class B { static check(arg:PayloadGeneric): arg is PayloadB { return typeof arg == "string" } note: string constructor(arg: PayloadB) { this.note = arg} log = () => console.log("B/", this.note) } function wrap(arg: PayloadGeneric) { if (A.check(arg)) { // understands that arg is number return new A(arg) // and that arg is suitable for PayloadA } if (B.check(arg)) { // understands that arg is string return new B(arg) // and that arg is suitable for PayloadB } } const instanceA = wrap(999) // but here it doesn't understand the type const instanceB = wrap("adaptive") // neither here
(我知道PayloadA和PayloadB看起来有点多余,毕竟它们就是number和string,但这里只是用简单类型举例子,实际场景中会是自定义接口和断言,用类型别名是为了更清晰地表达我的意图)
你看,wrap函数只接受PayloadA或PayloadB类型的参数,内部的两个if判断里,TypeScript能正确识别arg的类型(比如A.check后知道arg是number,能匹配A的构造函数),但到了调用wrap的时候,它却没法自动推断返回的是A还是B的实例,甚至还会认为可能返回undefined——但逻辑上我已经处理了所有可能的输入情况。
我的问题是:明明已经覆盖了所有场景,TypeScript却无法识别,该怎么修复?我想要实现返回类型的自动收窄,而且不想硬编码返回类型为A | B,因为传入的类列表可能会变化:如果没有类的check方法匹配,返回类型应该是undefined;如果有匹配的,就自动推断出对应的类实例类型。
备注:内容来源于stack exchange,提问作者Vagif VALIYEV
相关产品推荐
相关产品推荐

