Get type from typeguard's type predicate
Asked Answered
B

1

11

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.

Breathing answered 30/5, 2020 at 3:13 Comment(0)
S
22

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

Slip answered 30/5, 2020 at 3:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.