Get type from typeguard's type predicate

Viewed 266

Typically, a typeguard's type is defined as such:

(value: unknown) => value is Type

Where the highlighted part is called a type predicate by the documentation:

(value: unknown) => **value is Type**

Going even forward, we could say (I don't know how, if even, the docs defines this) that the value is the typeguard's parameter, is is a TypeScript binary operator/keyword for defining type predicates and Type is the type the typeguard actually guarantee, the guaranteed type. Since we use typeguards to guarantee a value's type, we could say that Type is the most interesting part of the definition.

Being such, is it possible to extract Type from the type definition of a typeguard? How?

I'm thinking of something like:

type Type = typeof typeguard; // (value: unknown) => value is Type
type TypePredicate = TypePredicateOf<Type>; // value is Type
type GuaranteedType = IsOf<TypePredicate>; // Type

Where GuaranteedType is the desired result.


Googling around, I've only found answers about generic typeguards type definitions, but did not get how to get the Type part from it.

1 Answers

You can use conditional type inference with the infer keyword to extract the guarded type from a type guard signature. Something like:

type GuardedType<T> = T extends (x: any) => x is infer U ? U : never;

And given some user-defined type guards:

function isString(x: any): x is string {
  return typeof x === "string";
}

interface Foo {
  a: string;
}

function isFoo(x: any): x is Foo {
  return "a" in x && typeof x.a === "string"
}

You can see that it works as advertised:

type S = GuardedType<typeof isString>; // string
type F = GuardedType<typeof isFoo>; // Foo

Okay, hope that helps; good luck!

Playground link to code

Related