一种在 Typescript 模板文字中标记任意字符串的方法

时间:2021-03-29 09:12:34

标签: typescript template-literals

自 TypeScript 4.1 发布以来,我正在尝试做与许多其他开发人员可能一直在尝试的完全相同的事情:严格键入具有预定模式的所有字符串。

虽然我设法为日期字符串找到了一个很好的折衷方案,但我现在面临着十六进制颜色代码的挑战。

显然是尝试 HEX = 0 的幼稚方式 | 1 | ... | "E" | "F" 然后声明

type HEX_CODE = `#${HEX}${HEX}${HEX}${HEX}${HEX}${HEX}`;

由于太多类型的联合使类型变得过于复杂。

很公平。

所以我想我至少会尝试在十六进制代码前面添加 # 的要求,这意味着我会满足于这样的事情:

type HEX_CODE = `#${arbitraryString}`;

但是我想不出让这个工作的方法。有谁知道如何进行这项工作,或者在类型上进行另一种(可能更好)的妥协?

2 个答案:

答案 0 :(得分:2)

这不只是:

type HEX_CODE = `#${string}`;

typescript playground

答案 1 :(得分:1)

这里有一个解决方案:

更新

现在,如果字符串长度不等于 6 则抛出错误

type HexNumber = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
type HexString = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
type StringNumber<T extends number> = `${T}`
type HEX = HexNumber | StringNumber<HexNumber> | HexString;

type Check<T extends string, Cache extends readonly string[] = []> =
    T extends `${infer A}${infer Rest}`
    ? A extends HEX
    ? Check<Rest, [...Cache, A]> : A extends ''
    ? 1 : 2 : T extends '' ? Cache extends { length: 6 }
    ? Cache : 'String should have 6 chars. No more, no less' : never;

type Elem = string;

type Mapper<
    Arr extends ReadonlyArray<Elem>,
    Result extends string = ''
    > = Arr extends []
    ? Result
    : Arr extends [infer H]
    ? H extends Elem
    ? `${Result}${H}`
    : never
    : Arr extends readonly [infer H, ...infer Tail]
    ? Tail extends ReadonlyArray<Elem>
    ? H extends Elem
    ? Mapper<Tail, `${Result}${H}`>
    : never
    : never
    : never;


type Result = Mapper<Check<'abcdef'>> // allow
type Result2 = Mapper<Check<'00cdef'>> // allow
type Result3 = Mapper<Check<'z0cdef'>> // not allow
type Result4 = Mapper<Check<'00cdem'>> // not allow
type Result5 = Mapper<Check<'aaaaa'>> // to few arguments

Playground

你只能在实践中将我的解决方案用于函数参数

const hex = <T extends string, U extends {
    'valid': 'valid',
    'invalid': 'invalid',
}[Check<T> extends string[] ? Mapper<Check<T>> extends T ? 'valid' : never : 'invalid']>(value: T, ...rest: U extends 'valid' ? [] : [never]) => value

const result = hex('aaaaaf') // ok
const result2 = hex('aaaaaZ') // error

Playground 2

相关问题