#How might I infer the type a type-guard is guarding for?

23 messages · Page 1 of 1 (latest)

drowsy eagle
#

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?

sinful ivy
#
(value: Value) => value is infer U extends Value
#

Gives no type errors, but please test that it works correctly.

#

@drowsy eagle

drowsy eagle
#

@sinful ivy I'm still running into the same error I mentioned above. Am I missing something?

type Props<Value, When extends (value: Value) => value is any> = {
  value: Value
  when: When
  children(value: (value: Value) => value is infer U ? U : never): React.ReactNode
}
sinful ivy
#

You didn't add the extends Value

safe shellBOT
#
sandiford#0

Preview:```ts
import React from "react"

type Left<T> = {type: "left"; value: T}
type Right<T> = {type: "right"; value: T}
type Either<L, R> = Left<L> | Right<R>

const isLeft = <T extends any>(
either: Either<T, unknown>
): either is Left<T> => either.type === "left"
...```

sinful ivy
#

Check GuardedType2

drowsy eagle
#

🤦‍♂️ thank you

opaque kiln
drowsy eagle
#

Nah, i'm seeing the same thing. Bert solved a problem, but I'm still missing something.

sinful ivy
#

I didn't change the code, I just added a new type

#

It's not a like for like replacement, so not sure how I would try to fix the code as a whole

#
old:
type GuardedType<T> = T extends ((value: unknown) => value is infer U) ? U : never
new:
type GuardedType2<Fn, Value> = Fn extends ((value: Value) => value is infer U extends Value) ? U : never
drowsy eagle
#

^ i did the swap here

#

if you look at line 47, it still doesn't narrow but i'm not sure why

opaque kiln
#

I have a solution, but I'm not entirely satisfied with it:

safe shellBOT
#
nonspicyburrito#0

Preview:```ts
import React from "react"

type Left<T> = {type: "left"; value: T}
type Right<T> = {type: "right"; value: T}
type Either<L, R> = Left<L> | Right<R>

const isLeft = (either: {
type: unknown
}): either is {type: "left"} => either.type === "left"

const isRight = (either: {
type: unknown
}): either is {type: "right"}
...```

opaque kiln
#

Solid.js also has a component similar to your Match, you can look into their type implementation.

#

But otherwise the solution above works for your case.

drowsy eagle