Typescript 扩展具有泛型类型的接口导致约束错误的子类型
Typescript extending interface with generic type causes subtype of constraint error
我有一个抽象的 class,其默认状态值是在 ResourceState
界面中键入的。当我尝试将我的扩展 State
分配给我的摘要 class 的状态 属性 时,出现以下错误。我尝试了很多不同的方法来使用交集,但它仍然不起作用。我想要实现的是,我可以为状态 属性 提供一个通用接口,这样我就可以添加除默认值之外的更多值。
这是我得到的错误:
Type '{ items: never[]; isLoading: false; error: string; }' is not assignable to type 'State'.
'{ items: never[]; isLoading: false; error: string; }' is assignable to the constraint of type 'State', but 'State' could be instantiated with a different subtype of constraint 'ResourceState'.
这是我的代码:
export interface BaseItem {
id: string;
name: string;
}
export interface ResourceState < Item extends BaseItem > {
items: Item[];
selectedItem ? : Item;
isLoading: boolean;
error: string;
}
export abstract class Resource < Item extends BaseItem, State extends ResourceState < Item > , Mutations, Getters, Actions > {
state: State = { // this is where the error occurs
items: [],
isLoading: false,
error: '',
}
}
当你说 State extends ResourceState<Item>
时,你是说 State
需要符合 ResourceState<Item>
但因为这是一个通用类型参数,它可能不完全是 ResourceState<Item>
.
想象一下:
interface MyState extends ResourceState<{ a: 123 }> {
myCustomRequiredProperty: number
}
现在你将 MyState
作为 State
传递给你的 class,然后你构造状态:
state: State = { // this is where the error occurs
items: [],
isLoading: false,
error: '',
}
那么你的 state
变量将不会用 myCustomRequiredProperty
属性 构造,这是必需的。
这是打字稿(隐秘地)试图告诉你的错误。
如果你在 Resource
class 中构造状态变量,那么 State
不应该是通用的,因为你在 class 中的可执行代码不能知道可以一般传入的类型的所有属性。所以 State
不应该 extend ResourceState<Item>
,它应该恰好是 ResourceState<Item>
.
看起来像这样:
export abstract class Resource<Item extends BaseItem> {
state: ResourceState<Item> = {
items: [],
isLoading: false,
error: '',
}
}
但是,如果您希望能够向状态添加属性,那么没有一些初始值就无法做到这一点。您需要以某种方式初始化这些未知属性。为此,您将使用上面的方法,但使用接受任何类型的构造函数是完整状态,然后使用具有该信息的对象填充该类型的未知属性。
export abstract class Resource<
Item extends BaseItem,
State extends ResourceState<Item>
> {
state: State
constructor(initialState: State) {
this.state = {
...initialState, // Fills in extended properties
items: [],
isLoading: false,
error: '',
}
}
}
我有一个抽象的 class,其默认状态值是在 ResourceState
界面中键入的。当我尝试将我的扩展 State
分配给我的摘要 class 的状态 属性 时,出现以下错误。我尝试了很多不同的方法来使用交集,但它仍然不起作用。我想要实现的是,我可以为状态 属性 提供一个通用接口,这样我就可以添加除默认值之外的更多值。
这是我得到的错误:
Type '{ items: never[]; isLoading: false; error: string; }' is not assignable to type 'State'. '{ items: never[]; isLoading: false; error: string; }' is assignable to the constraint of type 'State', but 'State' could be instantiated with a different subtype of constraint 'ResourceState'.
这是我的代码:
export interface BaseItem {
id: string;
name: string;
}
export interface ResourceState < Item extends BaseItem > {
items: Item[];
selectedItem ? : Item;
isLoading: boolean;
error: string;
}
export abstract class Resource < Item extends BaseItem, State extends ResourceState < Item > , Mutations, Getters, Actions > {
state: State = { // this is where the error occurs
items: [],
isLoading: false,
error: '',
}
}
当你说 State extends ResourceState<Item>
时,你是说 State
需要符合 ResourceState<Item>
但因为这是一个通用类型参数,它可能不完全是 ResourceState<Item>
.
想象一下:
interface MyState extends ResourceState<{ a: 123 }> {
myCustomRequiredProperty: number
}
现在你将 MyState
作为 State
传递给你的 class,然后你构造状态:
state: State = { // this is where the error occurs
items: [],
isLoading: false,
error: '',
}
那么你的 state
变量将不会用 myCustomRequiredProperty
属性 构造,这是必需的。
这是打字稿(隐秘地)试图告诉你的错误。
如果你在 Resource
class 中构造状态变量,那么 State
不应该是通用的,因为你在 class 中的可执行代码不能知道可以一般传入的类型的所有属性。所以 State
不应该 extend ResourceState<Item>
,它应该恰好是 ResourceState<Item>
.
看起来像这样:
export abstract class Resource<Item extends BaseItem> {
state: ResourceState<Item> = {
items: [],
isLoading: false,
error: '',
}
}
但是,如果您希望能够向状态添加属性,那么没有一些初始值就无法做到这一点。您需要以某种方式初始化这些未知属性。为此,您将使用上面的方法,但使用接受任何类型的构造函数是完整状态,然后使用具有该信息的对象填充该类型的未知属性。
export abstract class Resource<
Item extends BaseItem,
State extends ResourceState<Item>
> {
state: State
constructor(initialState: State) {
this.state = {
...initialState, // Fills in extended properties
items: [],
isLoading: false,
error: '',
}
}
}