constructor
static
,而是许多采用不同输入,对其进行转换,验证并最终返回类的新实例的方法。由于其原型继承,这在JavaScript中完美工作:
class Base {
static newX(...args) {
// here I need to validate and transform `args`
return new this(...args);
}
static newY(...args) {
// here I need to transform `args`
return this.newX(...args);
}
toString() {
return `${this.constructor.name}:${JSON.stringify(this)}`
}
}
class A extends Base {
constructor() {
super();
}
}
class B extends Base {
constructor(n){
super();
this.n = n;
}
static newX(n) {
// here I need to do something different from Base.newX
return new this(n);
}
}
class C extends Base {
constructor(str, n){
super();
this.str = str;
this.n = n;
}
static newY(str, n) {
// here I need to do something different from Base.newY
return this.newX(str, n);
}
}
// everything should work
console.log(`${A.newX()}`);
console.log(`${A.newY()}`);
console.log(`${B.newX(1)}`);
console.log(`${B.newY(1)}`);
console.log(`${C.newX("hi", 0)}`);
console.log(`${C.newY("hi", 0)}`);
Microsoft/Typescript#4628中描述了这里的主要问题。子类中的static
Base.newX("anything I'd like")
,那么A.new
"anything I'd like"
number
需要接受declare class Super {
method<A extends unknown[], T>(...a: A): T;
}
class Sub extends Super {
method(n: number) { return super.method(n) }; // error!
}
,它不能突然决定它仅接受static
。如果您使用非静态方法尝试了,这与您遇到的问题相同:
static
当然,Liskov替换原理的静态方面有一个很大的例外:构造函数本身。始终允许您让子类构造函数与超类构造函数完全不同的参数。该例外是在打字稿中刻出的,以允许惯用的JavaScript类层次结构主要工作。但这确实意味着您不能仅仅将子类构造函数替换为超类构造函数,并期望它能起作用。
那么,为什么他们也不能对静态事物造成同样的例外呢?这就是Microsoft/Typescript#4628的内容。当前情况如下所述,Microsoft/Typescript#4628的评论::
静态继承ISES6规格的一部分,但是...
将完全接受任何参数,从根本上“不受限制”。 因此,现在您可以将您的子类类型标记为您想要的任何东西。当然,您需要标记这些类型,因为从父母那里继承的类型太松了:
- 有些人使用类静态(即具有
第一组想要此检查,就像他们想要一般的classance sidance的一般替代性检查
Committed
属性的构造函数)的静态侧,有些人不付诸实践第二组根本不在乎他们的成员是否对齐
- 第一组在使用站点上检测到其可替代性失败,这比在声明站点更糟,但仍然(大部分)起作用
第二组在我们目前的设计中不幸
- 因此,如果您想将静态继承用于此目的,则需要解决它。最简单的方法是松开基类静态方法的类型安全性,以便子类只能完成他们想要的事情。这就是
结论:尝试删除检查静态侧的检查性的检查,然后查看哪种错误消失(主要是在基线中,因为我们在现实世界中的基本线中大多具有干净的代码)。取决于这些结果。
这里有暂定标签。您在这里主要是“第二组”。不幸的是...此后,这个问题实际上都没有发生。有一些相关的建议,但它们仍在开放,没有任何迹象都会改变。
any
type的来源:class Base { static newX(this: new (...args: any) => Base, ...args: any) { return new this(...args); } static newY(this: { newX(...args: any): Base }, ...args: any) { return this.newX(...args); } toString() { return `${this.constructor.name}:${JSON.stringify(this)}` } }
- 与类型的参数相比,NOW
和
newX
newY
unknown[]
不漂亮,但是有效。如果打字稿的规则对自己是什么,并且不允许妨碍您的方式,那么您可能会考虑完全从类层次结构进行重构。但是,这种重构的范围不超出所要求的问题。 to代码的链接链接