I have written this example (https://tsplay.dev/mL0GZm), which I think is pretty close to what I want. I can see that my problem is that When (on lines 22 and 23) probably also needs to accept Value as a generic type variable (or at least be aware of it in some way). I've tried rewriting GuardedType (line 14) to look like this:
type GuardedType<Fn, Value> = Fn extends (value: Value) => value is infer U ? U : never
but then I get this error:
A type predicate's type must be assignable to its parameter's type.
Type 'U' is not assignable to type 'Value'.
'Value' could be instantiated with an arbitrary type which could be unrelated to 'U'.(2677)
Is there a way to pull this off?
A link shortener for the TypeScript Playground