【问题标题】:How to use spread operator in typescript as argument to a function?如何在打字稿中使用扩展运算符作为函数的参数?
【发布时间】:2022-01-16 08:49:04
【问题描述】:

我希望能够将数组传播到函数的参数中, 但我得到了一个扩展参数必须具有元组类型或传递给休息参数.ts(2556)

  const currentColor: string = context.brandingPersonal.customColor; // rgba string 
  const numberColor: [number, number, number, number] = currentColor
    .substring(5, currentColor.length - 1)
    .replace(/ /g, '')
    .split(',')
    .map((item) => Number(item));

  function getContrastColor(R: number, G: number, B: number, A?: number) {
    const brightness = R * 0.299 + G * 0.587 + B * 0.114 + (1 - A || 0) * 255;
    return brightness > 186 ? '#000000' : '#FFFFFF';
  }
  getContrastColor(...numberColor);

【问题讨论】:

  • TS 不知道numberColor 的类型是“元组”(TS 中的固定大小数组),因为元组需要定义为 const。在[255,50,50,0.1] 之后添加as const 以将类型从Array 缩小到[Number, Number, Number, Number]
  • 问题是函数有固定数量的参数,数组没有。你可以把它变成一个元组,使数组成为常量,或者使用rest(IMO 可能不会)。在网上搜索错误消息也可能提供其他选项。
  • @HKG 如果值为 rgb only 如何设置参数中的最后一个参数可选?
  • 只需A?: number
  • @HKG 我会更新我的代码来告诉你发生了什么

标签: typescript


【解决方案1】:

Here你可以找到在打字稿中创建数字范围的解释。

Here你可以找到我关于创建数字范围的文章。

可以通过静态类型分析实现额外的安全性:

type MAXIMUM_ALLOWED_BOUNDARY = 256

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

type Octal = ComputeRange<MAXIMUM_ALLOWED_BOUNDARY>[number]

type Digits = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

type AlphaChanel = `0.${Digits}` | '1.0'

type RGBA<Alpha extends number = 1.0> = [Octal, Octal, Octal, (`${Alpha}` extends AlphaChanel ? Alpha : never)?]

function getContrastColor<Alpha extends number>(...[R, G, B, a]: RGBA<Alpha>) {
    const A = a || 1;

    const brightness = R * 0.299 + G * 0.587 + B * 0.114 + (1 - A || 0) * 255;

    return brightness > 186 ? '#000000' : '#FFFFFF';
}

getContrastColor(10, 20, 30, 0.2); // ok
getContrastColor(256, 20, 30, 0.2); // error, 256 is out of the range
getContrastColor(255, 20, 30, 0.22); // error, 0.22 should be 0.2

Playground

RGBA 实用程序类型充当类型验证器,同时充当所有有效 RGB 元组的类型。您可以找到更多信息 herehere。如果 A 是允许的 alpha 通道值,则返回 A,否则 - never

AlphaChanel - 是所有允许值的联合。您可能已经注意到我在0. 之后只允许一位数字。如果你想允许更多,请使用这个:

type AlphaChanel = `0.${ComputeRange<999>[number]}` | '1.0'

如果你对hex验证感兴趣,可以查看this的文章或者this的回答

【讨论】:

    【解决方案2】:

    split 不保证它将在运行时输出多少块。传递像“foo”这样的字符串会使您的例程失败,因为您的函数不会返回有效的 4 元组。

    你可以使用这样的东西来保证正确的元组输出:

    function getNumberTuple(color: string) : [number, number, number, number?] {
      const rgba = color.substring(5, color.length - 1).replace(/ /g, "")
      const numbers = rgba.split(",").map((item) => Number(item));
      return [numbers[0] || 0, numbers[1] || 0, numbers[2] || 0, numbers[3]]
    }
    
    function getContrastColor(R: number, G: number, B: number, A?: number) { /* ... */}
    
    getContrastColor(...getNumberTuple("color 123,123,123"));
    

    【讨论】:

      【解决方案3】:

      使用元组怎么样?

      const numberColor = [255,50,50,0.1]
      
      // Check RGBA
      function getContrastColor([ R, G, B, A ]:[number, number, number, number]) {
        const brightness = R * 0.299 + G * 0.587 + B * 0.114 + (1 - A) * 255;
      
        return brightness > 186 ? '#000000' : '#FFFFFF';
      }
      
      // function call with spread operator 
      getContrastColor(numberColor);
      

      【讨论】:

      • 问题是我希望它同时支持 rgba 和 rgb 所以我可以有 3 个数字或 4 个数字
      • “number[]”类型的参数不能分配给“[number, number, number, number]”类型的参数。目标需要 4 个元素,但源可能有更少的.ts(2345)
      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 2018-07-25
      • 1970-01-01
      • 2019-09-26
      • 2017-12-09
      • 1970-01-01
      • 2019-06-14
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多