将一种用作公共构造器的多态性静态方法的类型

问题描述 投票:0回答:1
E。为了创建这些类的实例,不应使用

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)}`);


如何使用Typescript给出此代码的类型? 我以几种不同的方式尝试了,但是每个方法都有问题。这是一个打字稿的操场链接,可以查看我的尝试并进行此件代码:
https://tsplay.dev/w2oa4n

Microsoft/Typescript#4628中描述了这里的主要问题。子类中的static

方法不适合
typescript constructor this abstract-class prototypal-inheritance
1个回答
0
投票
中的方法。 TypeScript在类的静态侧具有与实例一侧相同的类型限制:如果您覆盖某些内容,则需要确保可以替换为基础,也许需要遵守Liskov替代原则。 。因此,如果您可以写

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规格的一部分,但是...

  • 有些人使用类静态(即具有

    Committed属性的构造函数)的静态侧,有些人不付诸实践

  • 第一组想要此检查,就像他们想要一般的classance sidance的一般替代性检查
  • 第二组根本不在乎他们的成员是否对齐
    

  • 第一组在使用站点上检测到其可替代性失败,这比在声明站点更糟,但仍然(大部分)起作用

    第二组在我们目前的设计中不幸
  • 结论:尝试删除检查静态侧的检查性的检查,然后查看哪种错误消失(主要是在基线中,因为我们在现实世界中的基本线中大多具有干净的代码)。取决于这些结果。

    这里有暂定标签。
    
    您在这里主要是“第二组”。不幸的是...此后,这个问题实际上都没有发生。有一些相关的建议,但它们仍在开放,没有任何迹象都会改变。

  • 因此,如果您想将静态继承用于此目的,则需要解决它。最简单的方法是松开基类静态方法的类型安全性,以便子类只能完成他们想要的事情。这就是
  • anytype的来源:

  • 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代码的链接链接

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.