使用泛型类型混淆TypeScript错误

时间:2018-07-03 07:46:44

标签: typescript

我有这样的设置:

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。

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