使用嵌套的typescript泛型时出现奇怪的typescript错误



所以,我正在研究一些typescript代码,我发现了这个奇怪的bug,我不知道为什么会发生。我刚开始学习语言,所以这可能是一个新手问题,但无论如何,这对我来说真的很奇怪。

首先,我有一个typescript playground所以你们可以迭代它来帮助我解决它

无论如何,这是我正在处理的代码,只是一个例子:

class Model {
fields!: ModelFields;
options!: ModelOptions<this>;
}
class ModelWithoutIndex {
fields!: ModelFields;
options!: ModelOptionsWithoutIndex<this>;
}
class ModelWithIndexNotInBrackets {
fields!: ModelFields;
options!: ModelOptionsNotInBracket<this>;
}
class User extends Model {
fields = {
a: FieldTypes.BOOL
}
//                        V - Why? and how to solve it?
options: ModelOptions<this> = {
indexes: [{
unique: true,
fields: ['a']
}]
}
}
class UserWithoutIndex extends ModelWithoutIndex {
fields = {
a: FieldTypes.BOOL
}
//                                   V - This works, why???? You know what's strange, it just don't work because ModelIndex is an Object defined in {}
options: ModelOptionsWithoutIndex<this> = {
}
}
class UserWithIndexNotInBrackets extends ModelWithIndexNotInBrackets {
fields = {
a: FieldTypes.BOOL
}
//                                   V - As i said, why this works?, This doesn't make sense to me
options: ModelOptionsNotInBracket<this> = {
}
}
// ------------ TYPES ----------------
enum FieldTypes {
CHAR = 'CHAR',
BOOL = 'BOOL',
INT = 'INT'
}
type ModelIndex<M extends Model> = {
unique: true
fields: (keyof M["fields"])[]
}
type ModelIndexesNotInBracket<M extends ModelWithIndexNotInBrackets> = (keyof M["fields"])[]
type OrderingOfModelOptions<M extends Model | ModelWithoutIndex | ModelWithIndexNotInBrackets> = keyof M["fields"]|
keyof { [F in keyof M["fields"] as F extends string ? `-${F}` : never] : 1}

type ModelOptionsNotInBracket<M extends ModelWithIndexNotInBrackets> = {
indexes?: ModelIndexesNotInBracket<M>[];
ordering?: OrderingOfModelOptions<M>[];
}
type ModelOptionsWithoutIndex<M extends ModelWithoutIndex> = {
ordering?: OrderingOfModelOptions<M>[];
}
type ModelOptions<M extends Model> = {
indexes?: ModelIndex<M>[];
ordering?: OrderingOfModelOptions<M>[];
}
type ModelFields = {
[field: string]: FieldTypes
}

当我在调试时,我看到ModelIndex实际上被传递为ModelIndex<M & Model>,但这不是我想要的,我想要的是ModelIndex<M>,我不知道,我不明白为什么typescript会自动交叉。

Thanks much in advance

我提交了一个问题,他们回应了我,类型不会在类属性初始化器上自动断言。你可以在这里看到答案,但我也会为其他人翻译

您的属性字段具有类型{ a: FieldTypes },但是您的泛型ModelOptions<>需要类型参数来扩展Model。但是this的类型是{ fields: { a: FieldTypes } },它不扩展Model(即{ fields: ModelFields; options: ModelOptions<this> })。

当你正确输入属性字段时,它会工作:

class User extends Model {
fields: ModelFields = {
a: FieldTypes.BOOL
}
// ...
}

重新定义的属性类型不被继承。这将需要#10570。