Created
February 23, 2023 01:45
-
-
Save WoLfulus/99dc7fa1053a52b35ecf3b95d789b94a to your computer and use it in GitHub Desktop.
TypeScript build/compilation-time if/then/else blocks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Utilities | |
declare const TAG: unique symbol; | |
type TAG = typeof TAG; | |
export type Tagged<TagSymbol extends symbol> = { | |
readonly [TAG]: TagSymbol; | |
}; | |
export type WithTag<TagSymbol extends symbol, Target> = Tagged<TagSymbol> & | |
Target; | |
// PoC | |
declare const EitherTag: unique symbol; | |
type EitherTag = typeof EitherTag; | |
export type Either<T, F> = WithTag< | |
EitherTag, | |
{ | |
left: T; | |
right: F; | |
} | |
>; | |
declare const ElseTag: unique symbol; | |
type ElseTag = typeof ElseTag; | |
export type Else = WithTag<ElseTag, "else">; | |
export type Then< | |
True extends [any], | |
// @ts-ignore | |
E extends Else | undefined = undefined, | |
False extends [any] | undefined = undefined | |
> = Either< | |
True extends [infer TV] ? TV : True, | |
False extends [infer FV] ? FV : False | |
>; | |
export type If< | |
Statement extends boolean, | |
ThenBlock, | |
ElseBlock = undefined | |
> = ThenBlock extends Either<infer T, infer F> // If an either block | |
? Statement extends true | |
? T | |
: F | |
: ThenBlock extends Then< | |
infer ThenTrue, | |
// @ts-ignore | |
infer ThenElse, | |
infer ThenFalse | |
> // If a then block | |
? Statement extends true | |
? ThenTrue | |
: ThenFalse | |
: Statement extends true | |
? ThenBlock | |
: ElseBlock; | |
// Usage | |
type IsUpperCase<S extends string> = S extends Uppercase<S> ? Uppercase<S> extends S ? true: false: false; | |
type IUC<X extends string> = | |
If<IsUpperCase<X>, Then<[ | |
`"${X}" is uppercased` | |
], Else, [ | |
`"${X}" is not uppercased` | |
]>>; | |
type A = IUC<"I'm not uppercased">; | |
type B = IUC<"BUT I AM">; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment