Skip to content

Instantly share code, notes, and snippets.

@YBogomolov
Last active June 21, 2023 14:15
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save YBogomolov/7b3803e7bfcac3589804d01bfaf6d1aa to your computer and use it in GitHub Desktop.
Save YBogomolov/7b3803e7bfcac3589804d01bfaf6d1aa to your computer and use it in GitHub Desktop.
Type-level UUID
type VersionChar =
| '1' | '2' | '3' | '4' | '5';
type Char =
| '0' | '1' | '2' | '3'
| '4' | '5' | '6' | '7'
| '8' | '9' | 'a' | 'b'
| 'c' | 'd' | 'e' | 'f';
type Prev<X extends number> =
[never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...never[]][X];
type HasLength<S extends string, Len extends number> = [Len] extends [0]
? (S extends '' ? true : never)
: (S extends `${infer C}${infer Rest}`
? (Lowercase<C> extends Char ? HasLength<Rest, Prev<Len>> : never)
: never);
type Char4<S extends string> = true extends HasLength<S, 4> ? S : never;
type Char8<S extends string> = true extends HasLength<S, 8> ? S : never;
type Char12<S extends string> = true extends HasLength<S, 12> ? S : never;
type VersionGroup<S extends string> = S extends `${infer Version}${infer Rest}`
? (Version extends VersionChar
? (true extends HasLength<Rest, 3> ? S : never)
: never)
: never;
type NilUUID = '00000000-0000-0000-0000-000000000000';
type UUID<S extends string> = S extends NilUUID
? S
: (S extends `${infer S8}-${infer S4_1}-${infer S4_2}-${infer S4_3}-${infer S12}`
? (S8 extends Char8<S8>
? (S4_1 extends Char4<S4_1>
? (S4_2 extends VersionGroup<S4_2>
? (S4_3 extends Char4<S4_3>
? (S12 extends Char12<S12>
? S
: never)
: never)
: never)
: never)
: never)
: never);
const getUser = <S extends string>(id: UUID<S>): void => console.log(id);
getUser('00000000-0000-0000-0000-000000000000'); // ✅ special Nil UUID
getUser('11111111-1111-0111-1111-111111111111'); // ✅ zero is a special case
getUser('11111111-1111-1111-1111-111111111111'); // ✅ version 1
getUser('11111111-1111-2111-1111-111111111111'); // ✅ version 2
getUser('11111111-1111-3111-1111-111111111111'); // ✅ version 3
getUser('11111111-1111-4111-1111-111111111111'); // ✅ version 4
getUser('11111111-1111-5111-1111-111111111111'); // ✅ version 5
getUser('11111111-1111-6111-1111-111111111111'); // ✅ version 6 doesn't exist
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment