首页 > 解决方案 > 打字稿:具有不同参数的泛型数组

问题描述

考虑一个调用如下的函数:

func([
   {object: object1, key: someKeyOfObject1},
   {object: object2, key: someKeyOfObject2}
])

它有一个数组。我想强制该key字段包含保存在object. 每个物体都可以有不同的形状。

为单个对象构造这样的类型很容易:

type Type<T> = { obj: T, key: keyof T }

但是,我不知道如何从中创建一个数组,其中每个元素都将被强制执行。Type<any>[]都会丢弃类型。

标签: typescript

解决方案


在功能方面限制这一点很困难。我什至认为没有通用的方法可以做到这一点。

非泛型解决方案:函数重载

interface Item<TObject> {
  object: TObject
  key: keyof TObject
}

function func<T1, T2, T3, T4>(items: [Item<T1>, Item<T2>, Item<T3>, Item<T4>]): void
function func<T1, T2, T3>(items: [Item<T1>, Item<T2>, Item<T3>]): void
function func<T1, T2>(items: [Item<T1>, Item<T2>]): void
function func<T1>(items: Item<T1>[]): void {

}

func([
  { object: { a: '1' }, key: 'a' },
  { object: { b: '1' }, key: 'b' },
  { object: { c: '1' }, key: 'a' }, // not allowed
])

解决方案 2:在调用方强制执行类型 基本上,您依赖于实用程序函数。仍然有办法在这里出错并让编译器错过它(参见示例中的最后一项)

interface Item<TObject extends object> {
  object: TObject
  key: keyof TObject
}

function func(items: Item<any>[]) {

}

function createItem<T extends object>(object: T, key: keyof T): Item<T> {
  return {
    object,
    key
  }
}

func([
  createItem({ a: 1 }, 'a'),
  createItem({ b: 2 }, 'f'), // not allowed
  { object: { b: 2 }, key: 'f' }, // allowed
])

解决方案 3:使用通用 add 方法创建一个处理器对象

interface Item<TObject> {
  object: TObject
  key: keyof TObject
}

function createMyArrayProcessor() {
  const array: Item<any>[] = []

  return {
    add<T>(item: Item<T>) {
      array.push(item)

      return this
    },
    result() {
      // process the array here and return the result
    }
  }
}

const result = createMyArrayProcessor()
  .add({ object: { a: '1' }, key: 'a' })
  .add({ object: { b: '1' }, key: 'b' })
  .add({ object: { c: '1' }, key: 'a' }) // not allowed
  .result()

推荐阅读