typescript - 如何通过提供不同的类型来覆盖静态方法
问题描述
我有一个类 ( Foo
) 和一个子类 ( ),它们都是具有不同类型Bar extends Foo
的静态成员函数 ( )。func(...)
interface IFoo {
f1: string;
f2: string;
}
class Foo {
static func(data: Partial<IFoo>): Partial<IFoo> {
return { f1: data.f1, f2: data.f2 }
};
}
interface IBar extends Partial<IFoo>{
b1: string;
b2: string;
}
class Bar extends Foo {
static func(data: Partial<IBar>): Partial<IBar> {
return { ...Foo.func(data), b1: data.b1, b2: data.b2 }
};
}
在这个例子中,一切似乎都很好,但我需要不带类型修饰符的func
静态方法的第二个版本:Partial
interface IFoo {
f1: string
f2: string
}
class Foo {
static func(data: Partial<IFoo>): Partial<IFoo> {
return { f1: data.f1, f2: data.f2 }
};
static func2 = Foo.func as (data: IFoo) => IFoo; // This one
}
interface IBar extends Partial<IFoo>{
b1: string;
b2: string;
}
class Bar extends Foo {
static func(data: Partial<IBar>): Partial<IBar> {
return { ...Foo.func(data), b1: data.b1, b2: data.b2 }
};
static func2 = Bar.func as (data: IBar) => IBar; // This one
}
错误......func
并且func2
在技术上做同样的事情,除了func
允许有不完整的对象参数,相反func2
需要一个完全填充的参数。
但是我在“Bar”类上遇到了这个错误:
Class static side 'typeof Bar' incorrectly extends base class static side 'typeof Foo'.
Types of property 'func2' are incompatible.
Type '(data: IBar) => IBar' is not assignable to type '(data: IFoo) => IFoo'.
Types of parameters 'data' and 'data' are incompatible.
Type 'IFoo' is missing the following properties from type 'IBar': b1, b2ts(2417)
由于func
和func2
是相同的方法,但只是带有Partial
修饰符,有没有办法摆脱这个错误并能够func2
正确覆盖?
=====
编辑 :
@jcalz 解决方案都很好,但如果Foo
是抽象类,我收到以下错误:
Type 'typeof Foo' is not assignable to type '(new () => Foo) & Pick<typeof Foo, "prototype" | "func">'.
Type 'typeof Foo' is not assignable to type 'new () => Foo'.
Cannot assign an abstract constructor type to a non-abstract constructor type.ts(2322)
代码 :
const FooWithoutFunc2: (new () => Foo) & Omit<typeof Foo, "func2"> = Foo;
class Bar extends FooWithoutFunc2 {
// ...
}
我想我不能输入 Foo ,(new () => Foo)
因为它不是新的......我怎么能输入这样的摘要FooWithoutFunc2
?
谢谢你。
解决方案
如果你覆盖某些东西,它需要与你覆盖的东西保持兼容。在 TypeScript 中,这是在类的静态端以及类的实例端强制执行的。这意味着某人应该能够以Bar.func2()
与他们可以调用相同的方式进行调用Foo.func2()
。但是你不能Bar.func2({f1: "", f2: ""})
在你的定义中调用,所以 static 的一面Bar
没有正确地扩展Foo
.
因此,可能的修复:
Bar.func2({f1: "", f2: ""})
如果有人打电话回来,也许没关系{f1: "", f2: "", b1: undefined, b2: undefined}
。如果我要求Foo.func2
,而你递给我Bar.func2
,并且我像调用一样调用它Foo.func2
,我会得到一个带有这些未定义的额外属性的输出,但结果仍然是有效的IFoo
,所以我应该很高兴(或者至少它遵守签名)。这意味着Bar.func2
既是有效(x: IBar)=>IBar
的又是有效的(x: IFoo)=>IFoo
。因此,我们可以使用交集类型将其声明为两者,这相当于说Bar.func2
具有两个重载的调用签名:
class Bar extends Foo {
static func(data: Partial<IBar>): Partial<IBar> {
return { ...Foo.func(data), b1: data.b1, b2: data.b2 };
}
static func2 = Bar.func as ((data: IBar) => IBar) & typeof Foo.func2; // okay
}
Foo.func2({ f1: "", f2: "" });
Bar.func2({ f1: "", f2: "", b1: "", b2: "" });
Bar.func2({ f1: "", f2: "" }); // also okay because Bar.func2 extends Foo.func2
const foo: Foo = new Bar(); // but Bar still extends Foo (the instance side)
或者,也许你真的不希望任何人Bar.func2()
用不是IBar
参数的东西来调用。在那种情况下,这不可能是真的class Bar extends Foo
。的实例侧Bar
扩展了 的实例侧Foo
,但构造函数对象本身没有。我们也可以通过创建另一个构造函数对象来表达这一点,该对象Foo
生成实例但编译器不知道它具有func2
静态方法:
const FooWithoutFunc2: (new () => Foo) & Omit<typeof Foo, "func2"> = Foo;
class Bar extends FooWithoutFunc2 {
static func(data: Partial<IBar>): Partial<IBar> {
return { ...Foo.func(data), b1: data.b1, b2: data.b2 };
}
static func2 = Bar.func as ((data: IBar) => IBar); // okay
}
Foo.func2({ f1: "", f2: "" });
Bar.func2({ f1: "", f2: "", b1: "", b2: "" });
Bar.func2({ f1: "", f2: "" }); // error, typeof Bar doesn't extend typeof Foo anymore
const foo: Foo = new Bar(); // but Bar still extends Foo (the instance side)
现在Bar
仍然Foo
在实例端扩展,但在静态端 Bar
扩展。FooWithoutFunc2
我想这取决于您的用例是否适合您。无论如何,希望有所帮助;祝你好运!
推荐阅读
- c# - 使 ASP.NET MVC 控制器等待 void 函数的最佳方法?
- javascript - 随机词生成器不适用于 >50 个词
- django - 使用 django_rq 在 django 中一段时间(24 小时)后发送电子邮件
- android - 尝试通过 sendgrid 发送时未找到 Sourcset main
- java - Java:读取文件并将一行拆分为单独的字符串
- php - Laravel ftp 用 tus 上传
- python - 如何在 python 3.4 中声明多个 kwargs?
- php - PHP通过属性名称从具有对象的数组中删除一个元素
- c-preprocessor - 如何使用 boost 预处理器来简化 gcc neon 内联组装?
- java - 线程“主”java.lang.ClassCastException 中的异常:javafx.util.Pair 无法转换为 java.lang.Comparable