Typescript - 检查字符串是否仅包含特定字符的类型

3
如何对我们知道只包含特定值的字符串进行类型检查。
例如:const binary = '1010000101000'; 我们知道十进制表示的二进制值只会是1和0。为了更好地进行类型检查,这种类型的值需要一个好的类型定义。 type Binary = '0' | '1'; 不起作用,因为它们只表示字符串的单个字符。但是,关键在于如何为整个字符串声明/定义类型,我们知道该字符串只包含某些类型的字符。
问题并非是选择二进制值的接口,而是如何声明/定义预定义字符串值的类型。

可能是 TypeScript 中的受控 prop 名称 的重复问题。 - T.J. Crowder
1
linked question 的答案应用到这个 playground 中。虽然有点难看并且受限制(您无法超过此处所示的长度),但我认为类型系统没有更好的方法来完成这项任务。 - T.J. Crowder
通过这种方式添加类型检查会更加繁琐,而且带来的好处也不大。最好我添加一个正则表达式检查。 - AbhishekGowda28
在这种情况下,是的。 :-) - T.J. Crowder
FYI,目前还没有编译时正则表达式检查:https://github.com/microsoft/TypeScript/issues/41160 ;) - Matthieu Riegler
1个回答

7
您可以使用递归类型:
type BinDigit = "0" | "1"

type OnlyBinDigit<S> =
    S extends ""
        ? unknown
        : S extends `${BinDigit}${infer Tail}`
            ? OnlyBinDigit<Tail>
            : never




function onlyBinDigit<S extends string>(s: S & OnlyBinDigit<S>) {
}



onlyBinDigit("01010101010011"); // OK 
onlyBinDigit("010101012"); // NOK

为了解释这里的类型,OnlyBinDigit是一个递归类型。
  • 基础情形:空字符串返回类型unknown
  • 递归性:使用模板文字,我们可以将字符串分割并在尾部进行递归调用,直到达到空字符串。
  • 在非递归部分的模板文字中,如果第一个字符不匹配类型(这里是'0' | '1'),它将返回never,从而导致类型检查失败。

Playground


这个完美地运行了,你能解释一下这里发生了什么吗? - AbhishekGowda28

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接