-
-
Save phenomnomnominal/84e300d5de055298d505c4741281c2fd to your computer and use it in GitHub Desktop.
This file contains 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
type Freezable = { | |
unfreezable?: never; // Need to make the unfreezable property optional | |
}; | |
type Frozen<T extends Freezable = Freezable> = T & { | |
frozen: true; | |
}; | |
type Thawed<T> = T extends Frozen<infer R> | |
? R | |
: never; | |
function assertFreezable(thing: unknown): asserts thing is Freezable { | |
if (!thing || (thing as Freezable).unfreezable) { | |
throw new Error(`Can't freeze that! ❄️`); | |
} | |
} | |
function freeze<T extends Freezable = Freezable>(toFreeze: T): Frozen<T> { | |
assertFreezable(toFreeze); | |
(toFreeze as Frozen<T>).frozen = true; | |
return toFreeze as Frozen<T>; | |
} | |
function assertFrozen(thing: unknown): asserts thing is Frozen { | |
if (!thing || !(thing as Frozen).frozen) { | |
throw new Error(`Can't thaw that! ❄️`); | |
} | |
} | |
function thaw<T extends Frozen>(toThaw: T): Thawed<T> { | |
assertFrozen(toThaw); | |
delete toThaw.frozen; | |
return toThaw as Thawed<T>; | |
} | |
type Thing = Freezable & { thing: boolean }; // Need a type for the thing you're trying to freeze | |
freeze<Thing>({ thing: false, unfreezable: true }); // Not allowed | |
const frozenThing = freeze<Thing>({ thing: true }); | |
const thawed = thaw(frozenThing); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment