从本质上讲,我需要一个函数来克隆(即Deepcopies)共享某些公共属性的对象。 “公共属性”实质上只是一个用于操作的名为op
的标签。所以以前我有一些使用Flow输入的代码:
export function cloneExpr<E: Expr>(exp: E): E {
if (exp.op === POINT) {
return ((expr.makePoint(exp.p, exp.x, exp.y):any):E);
} ... etc
}
其中Expr
是Point
,Line
等一堆东西的结合,所有这些东西都具有此op
字段。强制播报有些丑陋,但至少可以奏效。也就是说,如果我cloneExpr
键入了Point
的对象,则返回对象的键入是Point
,而无需提供更多的键入信息。
现在,我想迁移到Typescript,但遇到很多麻烦。强制广播的return ((exp as any) as Point)
是在真空中工作的,但是我的类型防护不断丢失信息,因此,例如,在没有通过输入检查的情况下,我实际上无法从Point x
获取字段exp
。为了使Typeguard正常工作,我尝试了各种函数类型的变体,例如:
function cloneExpr<T extends Expr>(exp: T): T
其中Expr
与Point | Line
类似。
function cloneExpr<T extends IsExpr>(exp: T): T
其中IsExpr
是我定义的一个接口,其中只有一个op
字段。
function cloneExpr(exp: Expr): Expr
,但是显然我永远也不会得到正确的输入类型。
所以我没有得到类型保护,或者返回类型不是我输入的特定类型。我也尝试过使用Interfaces重新定义对象,然后提供用户定义的typeguard,但没有,但无济于事。
在Typescript中执行此操作的正确方法是什么?多谢。
答案 0 :(得分:2)
在测试exp
时无法将E
从Point
缩小到exp.op === POINT
(或类似的东西)将由this suggestion解决。同时,通过将参数复制到类型为Expr
的局部变量中,可以实现与Flow相同的类型安全性:
export function cloneExpr<E extends Expr>(exp: E): E {
const exp1: Expr = exp;
if (exp1.op === POINT) {
return expr.makePoint(exp1.p, exp1.x, exp1.y) as any as E;
}
// ...
}