打字稿抱怨类型永远不能分配给简单泛型类中的类型 K

时间:2021-02-04 09:40:39

标签: typescript

我有一个通用的 Action-Class,它接受 T(未知对象)和 K(参数数组)。 稍后应该扩展动作类以构造具有不同 T 和 K 的其他动作。但是,基本动作类已经抛出了我不明白的类型错误。我能想到的最小例子是:

type ActionObjects = Record<string, unknown>
type ActionArgs = Array<any>
export class Action<T extends ActionObjects = ActionObjects, K extends Array<any> = ActionArgs> {
  static actionName: string
  objectStore: T = {} // ERROR 1
  args: K = [] // ERROR 2

  async redo (objects: T, ...args: K) {
    this.objectStore = objects
    this.args = args

    // other stuff
  }
}

Typesript Playground

错误是:

  1. 类型“{}”不可分配给类型“T”。
  2. 类型“never[]”不能分配给类型“K”。

我做错了什么?

如果可以自动将 actionName 映射到所需的 ActionObjects 和 ActionArgs,那将是一个奖励:)

1 个答案:

答案 0 :(得分:1)

对于第一个类型 T,它可以是具有 string: unknown 属性的任何类型。因此空对象无效。如果 T 是接口怎么办,

interface SomeType {
  prop1: unknown;
  prop2: unknown;
}

显然 {} 与此类型不兼容。不要对泛型类型能够是任何类型并能够在它们的位置使用任何类型感到困惑。 T 可以有多种类型这一事实意味着您可以使用它(和分配给它)的方式实际上受到限制。

在这种情况下,我可能会使用 T | null 类型来表示您的 objectStore 属性并将其初始化为 null。

对于第二个错误,非常相似。 K 可以是扩展数组的任何东西 - 因此它可能是一个非常复杂的对象,具有许多不在简单数组中的功能。这就是空数组无效的原因。这可以通过将项目类型设为 K 然后指定 K[] 来解决,如下所示。

export class Action<T extends ActionObjects = ActionObjects, K = any> {
  static actionName: string

  objectStore: T | null = null;
  args: K[] = [];

  async redo (object: T, ...args: K[]) {
    this.objectStore = object
    this.args = args

    // other stuff
  }
}