如何在 Typescript 中创建 UUID 模板文字类型?

obi*_*ahn 5 uuid types typescript

有人成功地使用新的模板文字类型在 Typescript 中编写了 UUID 类型吗?

例如: const id:UUID = "f172b0f1-ea0a-4116-a12c-fc339cb451b6"

这个人在这里尝试过:UUID Tweet

但类型太复杂:“表达式生成的联合类型太复杂而无法表示。(2590)”:示例

他的类型:

type Alphabetic = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
type Alphanumeric = Alphabetic | Numeric

type Repeat<
    Char extends string,
    Count extends number,
    Joined extends string = ``,
    Acc extends 0[] = []
> = Acc['length'] extends Count ? Joined : Repeat<Char, Count, `${Joined}${Char}`, [0,...Acc]>

type UUIDV4 = `${Repeat<Alphanumeric, 8>}-${Repeat<Alphanumeric, 4>}-${Repeat<Alphanumeric, 4>}-${Repeat<Alphanumeric, 4>}-${Repeat<Alphanumeric, 12>}````
Run Code Online (Sandbox Code Playgroud)

Ren*_*ger 8

Yuri Bogolomov 在他的博客上发布了一个解决方案: https: //ybogomolov.me/type-level-uuid/

\n

这是他的解决方案(参见TypeScript Playground):

\n
type VersionChar =\n    | \'1\' | \'2\' | \'3\' | \'4\' | \'5\';\n\ntype Char =\n    | \'0\' | \'1\' | \'2\' | \'3\'\n    | \'4\' | \'5\' | \'6\' | \'7\'\n    | \'8\' | \'9\' | \'a\' | \'b\'\n    | \'c\' | \'d\' | \'e\' | \'f\';\n\ntype Prev<X extends number> =\n    [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...never[]][X];\n\ntype HasLength<S extends string, Len extends number> = [Len] extends [0]\n    ? (S extends \'\' ? true : never)\n    : (S extends `${infer C}${infer Rest}`\n        ? (Lowercase<C> extends Char ? HasLength<Rest, Prev<Len>> : never)\n        : never);\n\ntype Char4<S extends string> = true extends HasLength<S, 4> ? S : never;\ntype Char8<S extends string> = true extends HasLength<S, 8> ? S : never;\ntype Char12<S extends string> = true extends HasLength<S, 12> ? S : never;\n\ntype VersionGroup<S extends string> = S extends `${infer Version}${infer Rest}`\n    ? (Version extends VersionChar\n        ? (true extends HasLength<Rest, 3> ? S : never)\n        : never)\n    : never;\n\ntype NilUUID = \'00000000-0000-0000-0000-000000000000\';\n\ntype UUID<S extends string> = S extends NilUUID\n    ? S\n    : (S extends `${infer S8}-${infer S4_1}-${infer S4_2}-${infer S4_3}-${infer S12}`\n        ? (S8 extends Char8<S8>\n            ? (S4_1 extends Char4<S4_1>\n                ? (S4_2 extends VersionGroup<S4_2>\n                    ? (S4_3 extends Char4<S4_3>\n                        ? (S12 extends Char12<S12>\n                            ? S\n                            : never)\n                        : never)\n                    : never)\n                : never)\n            : never)\n        : never);\n\n\nconst getUser = <S extends string>(id: UUID<S>): void => console.log(id);\n\ngetUser(\'00000000-0000-0000-0000-000000000000\'); // \xe2\x9c\x85  special Nil UUID\ngetUser(\'11111111-1111-0111-1111-111111111111\'); // \xe2\x9c\x85  error: version 0 is a special case\ngetUser(\'11111111-1111-1111-1111-111111111111\'); // \xe2\x9c\x85  version 1\ngetUser(\'11111111-1111-2111-1111-111111111111\'); // \xe2\x9c\x85  version 2\ngetUser(\'11111111-1111-3111-1111-111111111111\'); // \xe2\x9c\x85  version 3\ngetUser(\'11111111-1111-4111-1111-111111111111\'); // \xe2\x9c\x85  version 4\ngetUser(\'11111111-1111-5111-1111-111111111111\'); // \xe2\x9c\x85  version 5\ngetUser(\'11111111-1111-6111-1111-111111111111\'); // \xe2\x9c\x85  error: version 6 doesn\'t exist\ngetUser(\'11111111-1111-1111-1111-11111111111\');  // \xe2\x9c\x85  error: invalid format\n
Run Code Online (Sandbox Code Playgroud)\n