Typescript check for the 'any' type
Asked Answered
T

3

34

Is it possible to check for the exact any type using typescript conditionals?

type IsAny<T> = T extends any ? true : never

type A = IsAny<any> // true
type B = IsAny<number> // never
type C = IsAny<unknown> // never
type D = IsAny<never> // never
Turbellarian answered 5/4, 2019 at 18:18 Comment(1)
Possible duplicate of Disallow call with anyPetry
P
49

Yeah, you can test for any:

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N; 
type IsAny<T> = IfAny<T, true, never>;
type A = IsAny<any> // true
type B = IsAny<number> // never
type C = IsAny<unknown> // never
type D = IsAny<never> // never

The explanation for this is in this answer. In short, any is intentionally unsound, and violates the normal rules of types. You can detect this violation because it lets you do something crazy like assign 0 to 1.

Petry answered 5/4, 2019 at 18:47 Comment(3)
The simpler one type IfAny<T, Y, N> = T extends never ? Y : N; also seems to have same effect. It looks like T extends never is distributed over T even when T is never, not sure if it's intended or not.Stickney
@Stickney That is intended; never is considered the "empty union" so it always maps to never in a distributive conditional type. It is interesting that any doesn't get distributed, which is why that version of IfAny can distinguish any from never... of course it does so by returning never instead of N, which is probably not desired.Petry
This one from @types/react emits false (not never) when T is never: type IsExactlyAny<T> = boolean extends (T extends never ? true : false) ? true : false;Orbit
N
6

another way to detect IsAny:

type IsAny<T> = (
  unknown extends T
    ? [keyof T] extends [never] ? false : true
    : false
);

result of IsAny with some values

Newsprint answered 3/8, 2021 at 9:13 Comment(0)
A
2

You can (ab)use the fact that any is both a subtype and a supertype of almost1 everything. So the inner (Distributive) Conditional Type resolves to a Union of true | false (=boolean) instead of either of them. I checked if T extends never but it works with pretty much any other type too.

type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;

type A = IsAny<any> // true
type B = IsAny<number> // false
type C = IsAny<unknown> // false
type D = IsAny<never> // false
type E = IsAny<void> // false
type F = IsAny<{}> // false
type G = IsAny<object> // false
type H = IsAny<undefined> // false
type I = IsAny<null> // false

TypeScript Playground


1 except for never

Acro answered 9/11, 2023 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.