如何排除模板文字类型的子字符串?

Gil*_*bre 4 typescript template-literals

我想从模板文字类型(自 TypeScript 4.1 起可用)中排除一些子字符串,但我不知道是否可能。

例子:

我可以定义一个类型,说“这个字符串是一个包含 2 个或更多元素的元组”,即类似于'[string, number]'这个文字类型:

type TupleWithTwoOrMoreElements = `[${string}, ${string}]`;
Run Code Online (Sandbox Code Playgroud)

现在,我想做相反的事情,即通过排除 substring创建一个文字类型,表示“这是一个类似元组的元素少于 2 个”, 。我想做这样的事情:

type TupleWithLessThanTwoElements = `[${someStringWithoutCommaOrSpace}]`;
Run Code Online (Sandbox Code Playgroud)

我认为不可能编写这种“regex-literal-type”,但我想知道是否有人能够解决这个问题。

Lin*_*ste 7

(据我所知)不可能为“任何不带逗号的字符串”编写类型。但是,如果预先知道该字符串,则可以创建一个条件类型来检查该字符串是否包含逗号。

type HasComma<S extends string, IfTrue = true, IfFalse = false> = 
  S extends `${string},${string}` ? IfTrue : IfFalse;
Run Code Online (Sandbox Code Playgroud)
type A = HasComma<','> // true
type B = HasComma<'string'> // false
type C = HasComma<'[string, number]'> // true
Run Code Online (Sandbox Code Playgroud)

因此,给定一个文字字符串,我们可以验证它并确保它是一个只有一个元素的元组。

type ValidateOneTuple<S extends string, IfValid = S, IfInvalid = never> = 
  HasComma<S, IfInvalid, S extends `[${string}]` ? IfValid : IfInvalid>
Run Code Online (Sandbox Code Playgroud)
type A = ValidateOneTuple<'[string, number]'> // never
type B = ValidateOneTuple<'[string]'> // "[string]"
type C = ValidateOneTuple<'[str,ing]'> // never
Run Code Online (Sandbox Code Playgroud)

Typescript Playground 链接

  • 这意味着虽然您不能将“TupleWithLessThanTwoElements”表示为*特定*类型,但您可以将其表示为对泛型类型的约束,并使用像[this](https://tsplay.dev/NVnLZN ) 验证。 (4认同)