繁体   English   中英

TypeScript 数组联合类型在 function 参数中

[英]TypeScript Array Union Type in function parameters

我有一个联合类型的各种特定长度的数组:

[ number ] | [ number, number ] | [ number, number, number, number ]

如您所见,对具有一个元素、两个元素或四个元素的数组有要求。

我正在尝试创建一个 object ,其中包含具有这些长度之一的 function 。 如何编写类型定义以允许这样做?

TS游乐场

例子:

const people: {
    name: string,
    address: Address,
    work: (numbers: [ number ] | [ number, number ] | [ number, number, number, number ]) => any
}[] = [
    {
        name: "Bob",
        address: new Address(),
        work: function(numbers: [ number ]): number {
            // Implementation returning number
        }
    },
    {
        name: "Ashley",
        address: new Address(),
        work: function(numbers: [ number, number, number, number ]): boolean {
            // Implementation returning boolean
        }
    },
    {
        name: "Michael",
        address: new Address(),
        work: function(numbers: [ number, number ]): number {
            // Implementation returning number
        }
    },
]

目前,它给了我错误:

错误信息

类型 '(numbers: [number]) => number' 不可分配给类型 '(numbers: [number] | [number, number] | [number, number, number, number]) => any'。 参数 'numbers' 和 'numbers' 的类型不兼容。 键入'[数字] | [号码,号码] | [number, number, number, number]' 不能分配给类型 '[number]'。 类型 '[number, number]' 不能分配给类型 '[number]'。 源有 2 个元素,但目标只允许 1.ts(2322)

- - - - 编辑 - - - -

我已经应用了评论中的建议,并将所有可能的调用放入单独的 function 联合而不是数组联合:

const people: {
    name: string,
    address: Address,
    work: ((numbers: [ number ]) => any) | ((numbers: [ number, number ]) => any) | ((numbers: [ number, number, number, number ]) => any)
}[] = [

现在尝试从此数组调用 function 时:

 people[1].work([2, 8, 6, 4])

它现在抛出以下错误:

类型号不可分配给从不类型

在 VSCode 中,我发现这就是为什么:

“交集 '[number] & [number, number] & [number, number, number, number]' 减少为 'never' 因为属性 'length' 在某些成分中具有冲突类型。”

更新您需要在这里使用双变量

class Address { }

type Tuple<
  N extends number,
  Item = number,
  Result extends Array<unknown> = [],
  > =
  (Result['length'] extends N
    ? Result
    : Tuple<N, Item, [...Result, number]>
  )


interface WorkFn {
  work(numbers: Tuple<1> | Tuple<2> | Tuple<4>): any
}

interface Person extends WorkFn {
  name: string,
  address: Address,
}

const people: Person[] = [
  {
    name: "Bob",
    address: new Address(),
    work(numbers: Tuple<1>) {
      const [myNumber] = numbers;

      return myNumber * 6
    }
  },
  {
    name: "Ashley",
    address: new Address(),
    work: function (numbers: Tuple<4>): boolean {
      const [myNumber, anotherNumber, someNumber, replaceNumber] = numbers;

      return myNumber === anotherNumber && someNumber === replaceNumber;
    }
  },
  {
    name: "Michael",
    address: new Address(),
    work: function (numbers: Tuple<2>): number {
      const [myNumber, anotherNumber] = numbers;

      return myNumber * anotherNumber;
    }
  },
]

TypeScript操场

在这里您可以找到方法类型和箭头bivariance类型和关于双变量之间的区别

另外,请注意,它不是 100% 安全的

我的建议是使用通用 function 来创建people数组。

function createPeople<
  T extends {
    name: string,
    address: Address,
    work: ((numbers: [ number ]) => any) | ((numbers: [ number, number ]) => any) | ((numbers: [number, number, number, number]) => any)
  }[]
>(p: [...T]){
  return p
}

const people = createPeople([
  {
    name: "Bob",
    address: new Address(),
    work: function(numbers: [ number ]): number {
      const [ myNumber ]: [ number ] = numbers;

      return myNumber * 6
    }
  },
  {
    name: "Ashley",
    address: new Address(),
    work: function(numbers: [ number, number, number, number ]): boolean {
      const [ myNumber, anotherNumber, someNumber, replaceNumber ]: [ number, number, number, number ]= numbers;

      return myNumber === anotherNumber && someNumber === replaceNumber;
    }
  },
  {
    name: "Michael",
    address: new Address(),
    work: function(numbers: [ number, number ]): number {
      const [ myNumber, anotherNumber ]: [ number, number ] = numbers;

      return myNumber * anotherNumber;
    }
  },
])

TypeScript 现在知道每个索引的回调是什么了。 这使得以下调用严格键入。

people[1].work([2, 8, 6, 4])
people[2].work([1, 2])

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM