Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 为什么通用约束会产生TS2417错误?_Typescript - Fatal编程技术网

Typescript 为什么通用约束会产生TS2417错误?

Typescript 为什么通用约束会产生TS2417错误?,typescript,Typescript,我在实现以下代码的Table类上遇到TypeScript 2417错误: 导出抽象类基表{ 受保护的构造函数(){} 静态生成器=类{ 受保护的构造函数(){} build():T{ 返回这个.buildTable(); } 受保护的buildTable():T{ 抛出新错误(“必须在子类中实现”); } }; } 导出类表扩展了BaseTable{ 私有构造函数(){ 超级(); } 静态生成器=类扩展了BaseTable.Builder{ 受保护的构造函数(){ 超级(); } 静态创建()

我在实现以下代码的Table类上遇到TypeScript 2417错误:

导出抽象类基表{
受保护的构造函数(){}
静态生成器=类{
受保护的构造函数(){}
build():T{
返回这个.buildTable();
}
受保护的buildTable():T{
抛出新错误(“必须在子类中实现”);
}
};
}
导出类表扩展了BaseTable{
私有构造函数(){
超级();
}
静态生成器=类扩展了BaseTable.Builder{
受保护的构造函数(){
超级();
}
静态创建(){
返回新的Table.Builder();
}
受保护的buildTable():表{
返回新表();
}
};
}
这会产生错误

Class static side 'typeof Table' incorrectly extends base class static side 'typeof BaseTable'.
  The types returned by '(new Builder()).build()' are incompatible between these types.
    Type 'Table' is not assignable to type 'T'.
      'Table' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'BaseTable'.(2417)
我的目标是拥有私有或受保护的构造函数,并且能够分两步调用代码

constbuilder=Table.builder.create();
const table=builder.build();
我认为这可能是由于
Builder
类是静态的,所以我尝试了以下方法:

导出抽象类基表{
构造函数(){}
}
导出命名空间基表{
导出抽象类生成器{
受保护的构造函数(){}
build():T{
返回这个.buildTable();
}
受保护的抽象构建表():T;
}
}
导出类表扩展了BaseTable{
构造函数(){
超级();
}
}
导出命名空间表{
导出类生成器扩展了BaseTable.Builder{
受保护的构造函数(){
超级();
}
静态创建(){
返回新的Table.Builder();
}
受保护的buildTable():表{
返回新表();
}
}
}
这段代码会产生相同的错误,并破坏了使用私有构造函数的目的


有人能给我解释一下这个错误以及如何实现这个代码吗。

问题是
BaseTable.Builder
被声明为一个泛型类,可以充当消费者想要的任何
T扩展BaseTable
。无论谁调用
new BaseTable.Builder()
(由于构造函数受
protected
),我都不清楚该调用谁)都可以指定
T
,比如
new BaseTable.Builder()

为了扩展
基表
,类的静态端和实例端都需要分别分配给
基表
的静态端和实例端。即既有接口端继承,也有静态端继承;有关静态继承是否可取的讨论,请参阅。但在可预见的未来,情况就是这样

因此
Table.Builder
必须可分配给
BaseTable.Builder
。但事实并非如此。虽然
Table.Builder
可以(由谁?)用来创建调用方想要的
build()
任何类型的
T扩展Basetable
,但是
Basetable.Builder
只能(由谁?)用来创建
build()
a
Table
的新事物

如果
Table
正确扩展
BaseTable
,并且如果我们去掉隐私/保护修饰符,以便有人能够实际演示键入问题(并忽略构造签名),那么问题是:

const hmm = new BaseTable.Builder<{ foo: string }>().build().foo; // okay
const AlsoBaseTable: typeof BaseTable = Table;
const uhOh = new AlsoBaseTable.Builder<{ foo: string }>().build().foo;
现在没有错误(除了可能的声明警告和其他
private
/
受保护的
东西在夜间颠簸之外),因为
Table.Builder
BaseTable.Builder
的真正子类型


我知道我可以从中删除泛型,但这意味着我必须将表实例转换为正确的类型。我也可以用香草JavaScript编写它。这段代码按原样编译和运行,并完全按照我希望和期望的方式执行。当我检查原型链时,它看起来正是我期望的样子。在一个完美的世界里,TypeScript会让我抑制这个错误,因为它对我的实现并不重要。这里的问题是关于TypeScript的,所以我试图找出是否有一种方法可以使用泛型来编写它,从而使TypeScript感到高兴。“我必须将表实例转换为正确的类型”。真正地演示一下。如果您只是想抑制错误,可以使用like。但是这个错误是有原因的,那就是您编写的
Table
没有正确扩展
BaseTable
。如果您的
类型正确,则
基表
错误,需要更改。这与我能得到的“有人能向我解释这个错误以及如何实现这个代码”非常接近。如果你有更好的答案,请告诉我。干杯我不知道
/@ts ignore
。从你的回答中,我对这个问题有了更多的理解,但这并不是我想要的。您反复地说
类没有正确地扩展
基表
,但您没有说如何扩展。我通过向
BaseTable.Builder
添加一个静态创建函数成功地消除了这个错误,尽管它永远不会被调用,但它只有在tsconfig中关闭
noImplicitAny
时才起作用,因为我还不知道如何键入它。我想知道如果我能将
BaseTable.Builder
抽象化和静态化,这是否会成为一个问题“你反复地说
Table
类没有正确地扩展
BaseTable
,但你没有说如何扩展。”
abstract class BaseTable {
    protected constructor() { }

    static Builder = class {
        protected constructor() { }

        build(): BaseTable {
            return this.buildTable();
        }

        protected buildTable(): BaseTable {
            throw new Error("Must be implemented in subclasses");
        }
    };
}


class Table extends BaseTable {
    private constructor() {
        super();
    }

    static Builder = class extends BaseTable.Builder {
        protected constructor() {
            super();
        }

        static create() {
            return new Table.Builder();
        }

        protected buildTable(): Table {
            return new Table();
        }
    };
}