28

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
Sam Denty
  • 3,693
  • 3
  • 30
  • 43
  • 1
    Possible duplicate of [Disallow call with any](https://stackoverflow.com/a/49928360/2887218) – jcalz Apr 05 '19 at 18:38

2 Answers2

39

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.

jcalz
  • 264,269
  • 27
  • 359
  • 360
  • 4
    The simpler one `type IfAny = 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. – artem Apr 05 '19 at 20:07
  • 4
    @artem That is intended; `never` is considered the "empty union" so it [always maps to `never` in a distributive conditional type](https://github.com/Microsoft/TypeScript/issues/23182#issuecomment-379094672). 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. – jcalz Apr 06 '19 at 00:02
  • 2
    This one from `@types/react` emits false (not never) when T is never: `type IsExactlyAny = boolean extends (T extends never ? true : false) ? true : false;` – ypresto Jul 10 '21 at 15:49
5

another way to detect IsAny:

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

result of IsAny with some values

eczn
  • 1,459
  • 2
  • 10
  • 15