let str: ByteString = "f1afe3"; // valid
let str1: ByteString = "fa1" // invalid, hex string length should be even
let str2: ByteString = "hello" //invalid, only hex allow
let str3: ByteString = "ffeeaa3300"; // valid
type ByteStringX = "" | `${Nybble}${ByteStringX}`; // error!
// ~~~~~~~~~~~ <--
// Type alias 'ByteStringX' circularly references itself.
您可以尝试展开该循环,但一旦尝试,编译器就会抱怨结果联合太大:
type ByteString0 = "" | Nybble | `${Nybble}${Nybble}`; // error!
// ----------------------------> ~~~~~~~~~~~~~~~~~~~~
// Expression produces a union type that is too complex to represent.
let str = byteString("f1afe3"); // okay
let str1 = byteString("fa1"); // error!
// Argument of type '"fa1"' is not assignable to parameter of type
// '"fa00" | "fa01" | "fa02" | "fa03" | "fa04" | "fa05" | "fa06" | ...
let str2 = byteString("hello"); // error!
// Argument of type '"hello"' is not assignable to parameter of type '"00" | "01" |
// "02" | "03" | "04" | "05" | "06" | "07" | "08" | "09" | ...
let str3 = byteString("ffeeaa3300"); // okay
1条答案
按热度按时间bvuwiixz1#
TypeScript中没有特定的类型是这样工作的,在microsoft/TypeScript#6579中有一个长期存在的特性请求,要求 * 正则表达式验证的字符串类型 *,在这里您大概可以编写如下内容
它就可以工作了。不幸的是TypeScript中没有这样的类型。你不能通过类型系统中的正则表达式来完成这一点。
引入模板文本类型后,上述问题已解决,因为它们允许对字符串文本类型进行操作。我们可以尝试将模板文本类型用于您的用例,但有几个主要问题阻止了我们。
首先,可以为有效的十六进制数字生成联合类型:
然后为有效的数字 * 对 * 编写一个类型:
但是你会被困在更深的地方。语言不允许你写循环模板文字类型,所以你不能这样做:
您可以尝试展开该循环,但一旦尝试,编译器就会抱怨结果联合太大:
TypeScript中的联合只能容纳大约100,000个成员......并且有超过230,000个有效的四位十六进制字符串。所以我们被卡住了。没有办法将
ByteString
写为特定的类型。我们 * 能 * 做的是编写一个generic类型
ByteString<T>
,它 * 验证 * 候选字符串类型T
,使得T extends ByteString<T>
当且仅当T
是有效的字节字符串类型。因此,它的行为就像一个约束而不是一个类型。为了使用它,我们需要一个helper函数来推断泛型类型参数T
。也就是说,代替你会有
以下是它的工作原理:
所以
ByteString<T>
是一个尾递归条件类型,如果T
是空字符串,那么我们接受它;这是基本情况。否则,我们尝试将T
解析为前两个十六进制数字D0
和D1
,然后是字符串R
的其余部分。如果解析成功,则通过计算ByteString<R>
进行递归。如果解析失败,则返回一个“close”有效字符串,这样,失败将产生一个有帮助的错误消息。让我们来测试一下:
str0
和str3
被接受,而str1
和str2
生成错误消息,说明输入不合适。"fa1"
失败,并与fa${Nybble}
进行比较,因为"1"
不是有效的数字对。"hello"
失败,并与${Nybble}
进行比较。因为"he"
不是有效的数字对。所以这是我们能得到的最接近你想要的东西。如果它适合你的用例,那就太好了。
如果不是,那么microsoft/TypeScript#41160中的正则表达式验证字符串类型仍然存在一个未解决的问题。您可能希望转到该问题,给予它一个👍,并描述您的用例以及为什么递归模板文本约束不足以满足要求。
Playground代码链接