【问题标题】:Typescript extending interface with generic type causes subtype of constraint error使用泛型类型扩展接口的打字稿导致约束错误的子类型
【发布时间】:2020-12-30 05:34:57
【问题描述】:

我有一个带有默认状态值的抽象类,在ResourceState 接口中输入。当我尝试将扩展的 State 分配给我的抽象类的 state 属性时,出现以下错误。我尝试了许多使用交叉点的不同方法,但它仍然不起作用。我想要实现的是,我可以为 state 属性提供一个通用接口,以便我可以添加除默认值之外的更多值。

这是我得到的错误:

输入 '{ items: never[]; isLoading:假;错误:字符串; }' 不可分配给类型 'State'。 '{ 项目:从不[]; isLoading:假;错误:字符串; }' 可分配给“State”类型的约束,但“State”可以用约束“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: '',
  }
}

【问题讨论】:

    标签: javascript typescript class types abstract-class


    【解决方案1】:

    当您说State extends ResourceState&lt;Item&gt; 时,您是在说State 需要符合ResourceState&lt;Item&gt;,但因为这是一个泛型类型参数,它可能不完全是ResourceState&lt;Item&gt;

    想象一下:

    interface MyState extends ResourceState<{ a: 123 }> {
      myCustomRequiredProperty: number
    }
    

    现在您将MyState 作为State 传递给您的班级,然后您使用以下方式构造状态:

      state: State = { // this is where the error occurs
        items: [],
        isLoading: false,
        error: '',
      }
    

    那么您的state 变量将不会使用myCustomRequiredProperty 属性构造,这是必需的。

    这是打字稿(神秘地)试图告诉你的错误。


    如果您在 Resource 类中构造状态变量,那么 State 不应该是通用的,因为您在此类中的可执行代码无法知道可以通用传入的类型的所有属性。所以State 不应该是 extend ResourceState&lt;Item&gt;,它应该是 ResourceState&lt;Item&gt;

    看起来像这样:

    export abstract class Resource<Item extends BaseItem> {
      state: ResourceState<Item> = {
        items: [],
        isLoading: false,
        error: '',
      }
    }
    

    Playground


    但是,如果您希望能够向状态添加属性,那么没有一些初始值就无法做到这一点。您需要以某种方式初始化那些未知属性。为此,您将使用上述方法,但使用接受任何类型为完整状态的构造函数,然后使用具有该信息的对象填充该类型的未知属性。

    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: '',
        }
      }
    }
    

    Playground

    【讨论】:

      猜你喜欢
      • 2020-08-03
      • 2022-11-23
      • 2021-04-20
      • 2016-07-18
      • 1970-01-01
      • 2018-12-27
      • 1970-01-01
      • 1970-01-01
      • 2014-09-23
      相关资源
      最近更新 更多