我有这样的设置:
export interface IListItem<TData = any> {
id: string;
isNew: boolean;
isOpen: boolean;
data: TData;
}
export interface IListStore<TItem> {
allowAddNew: boolean;
allowDelete: boolean;
items: IListItem<TItem>[];
}
export abstract class ListStore<TItem extends any, TState extends IListStore<TItem>> {
public state: TState;
public setState(newState: Partial<TState>): void {
}
public myMethod(): void {
const items: IListItem<TItem>[] = [];
this.setState({ // error on
items, // these three
}); // lines
}
}
但是我在setState
中的myMethod
方法调用周围遇到了这个错误:
Argument of type '{ items: IListItem<TItem>[]; }' is not assignable to
parameter of type 'Partial<TState>'.
哪个奇怪,因为这似乎对我来说是完全正确的任务?
使用VS Code v1.24.1和TypeScript v2.9.1。
答案 0 :(得分:0)
这是具有通用参数的映射类型的限制,您可以阅读为什么团队选择不实施此here的原因,但总结如下:
错误是设计使然,因为对于类型参数T扩展了C,T可分配给C,但C无法分配给T。在这种特定情况下,GenericSubValue无法分配给Partial,因为取代TValueSub的实际类型可能具有比GenericSubValue中的属性更进一步的属性。
例如,如果我们有一个字段,则该字段可以是更特殊的类型,因此我们假设的T
有效值实际上可能不是:
function test<T extends { foo: string }>(c: (p: Partial<T>) => void) : void {
c({
foo: "" // foo can be string but can be a more specialized type, such as a string literal type
})
}
// This needs to works, but since foo is more specialized, test can't know what a valid value for Partial<T> is
test<{ foo: 'just this value'}>(c=> {});
最简单的解决方案是使用类型声明:
,如果要执行此操作(并且可能使该类不适用于所有派生类型),则为最简单的解决方案:public myMethod(): void {
const items: IListItem<TItem>[] = [];
this.setState({
items,
} as Partial<TState>);
}