如何定义一个typescript类型来检查字符串值是否为有效的十六进制字符串?

ee7vknir  于 2022-12-14  发布在  TypeScript
关注(0)|答案(2)|浏览(154)

比如说:

let str: ByteString = "01afe3"; // valid
let str1: ByteString = "0a1" // invalid, hex string length should be even
let str2: ByteString = "hello" //invalid, only hex allow

该值可以是有效十六进制的任何字符串。
我已经尝试了下面的代码:

type HexChar = '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F';
type HexColor = `#${HexChar}${HexChar}${HexChar}${HexChar}${HexChar}${HexChar}`;
let color: HexColor = '#123456';

但这仅在值为固定长度时有效。
如果字符串值有效,我们需要一个可以处理任何长度的类型。

xurqigkl

xurqigkl1#

首先,您需要定义一个泛型HexType,它是一个条件类型并使用递归逻辑:

type HexChar = '0' | '1' | '2' | '3' | '4' 
  | '5' | '6'| '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
  | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';

type HexType<T extends string> = T extends `${infer R1}${infer R2}`
  ? R1 extends HexChar
    ? `${R1}${HexType<R2>}`
    : never
  : `${T}`;

然后创建一个helper函数,该函数可以获取任何值,但如果值类型不是HexType,则参数类型将是never,因此该函数会给您一个错误。

const MyHexTypeFunction = <T extends string>(value: HexType<T>) => value;

例如:

const value = MyHexTypeFunction("qxb12");   //gives never type and also gives error

const value2 = MyHexTypeFunction("AB234"); //value2 type is "AB234"

如果您希望十六进制字符串的长度为偶数,则可以使用另一个泛型类型和helper函数,如下所示:

type HasEvenLegth<T extends string> =
  T extends `${infer R1}${infer R2}${infer R3}`
    ? R3 extends ""
      ? T
      : `${R1}${R2}${HasEvenLegth<R3>}`
    : T extends ""
    ? ""
    : never;

const HasEvenLegthFunction = <T extends string>(value: HasEvenLegth<T>) => value;

例如:

const value3 = HasEvenLegthFunction(MyHexTypeFunction("E23a318")); 
//gives never type and also gives error because it has odd length

const value4 = HasEvenLegthFunction(MyHexTypeFunction("EQ")); 
//gives never type and also gives error because it has invalid character

const value5 = HasEvenLegthFunction(MyHexTypeFunction("AbbbB234")); 
//value5 type is "AbbbB234" it has no error

您可以阅读更多关于条件类型here的信息。

a64a0gku

a64a0gku2#

  • 谢谢-谢谢
    我找到的所有解决方案如下:
type HexChar = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F';

type HexType<T extends string> = 
  T extends `${infer R1}${infer R2}${infer R3}`
  ?  R1 extends HexChar
    ? R2 extends HexChar
      ? `${R1}${R2}${HexType<R3>}`
      : never
    : never
  : T extends `${infer R1}${infer R2}`
    ? R1 extends `${HexChar}${HexChar}`
      ? `${R1}${HexType<R2>}`
      : never
  : `${T}`;

/**
 * Converts a hex literal to string.
 * @param {string} hexStr - should be in format of hex literal, i.e. `/^([0-9a-fA-F]{2})*$/`
 */
export function hexToString<T extends string >(hexStr: HexType<T>): string {

  return hexStr;
};

hexToString("00aa")

但这需要一个辅助函数hexToString。我不需要辅助函数,我只需要一个类型。

相关问题