# How to conditionally detect the `any` type in TypeScript?

The expression:

```
type IsStrictlyAny<T> = (T extends never ? true : false) extends false ? false : true;
```

meets the criteria:

```
type IsStrictlyAny<T> = (T extends never ? true : false) extends false ? false : true;
type t1 = IsStrictlyAny<any>; // true
type t2 = IsStrictlyAny<unknown>; // false
type t3 = IsStrictlyAny<string>; // false
type t4 = IsStrictlyAny<never>; // false!
```

Playground.

This works because `T extends never ? true : false`

when treated as a distributed conditional type resolves to:

`boolean`

if`T`

is`any`

.`never`

if`T`

is`never`

.`false`

if`T`

is anything else.

And then since both `never`

and `false`

are assignable to `false`

, the final expression `(...) extends false ? false : true`

is `true`

only when `T`

is `any`

.

The simplest answer I've found is in the answer to the question this duplicates, and the explanation is in a related answer:

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

The short reason why this works is that `0 extends (1 & T)`

should be false for any type `T`

that "plays by the rules". `0`

isn't assignable to `1`

so it really shouldn't be assignable to `1 & T`

no matter what `T`

is. But `any`

doesn't play by the rules: `1 & any`

evaluates to `any`

, and `0 extends any`

is true.

Hope that helps; good luck!

Playground link to code

This is a good question, and at first I thought it was impossible, but after some investigating, I think there's a way.

First of all, check this out:

```
type Test = any extends never ? 'A' : 'B' // "A" | "B"
```

What that means is that typescript knows that `any`

could be anything, and it therefore cannot decide which side of the conditional to return, so it returns both sides as a union. I'm reasonably certain that `any`

is the only case that would behave this way.

So then you just need to try to detect if a union was returned or a single value. To do that, we use two tools.

First, note that the intersection of two incompatible types is `never`

.

```
type Test = 'A' & 'B' // never
```

Which makes sense, since a value cannot be two different strings at the same time.

Second, if we can get an intersection of all the members of the type union, we can then test see if it's `never`

, or it's any other valid type. This answer has a helper to convert a union to an intersection, so I wont bother explaining it.

So to some up:

- Check to see if type returns both sides of conditional as a union
- Merge the union members into an intersection, and see if the result is
`never`

.

```
// From: https://stackoverflow.com/a/50375286/62076
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
// If T is `any` a union of both side of the condition is returned.
type UnionForAny<T> = T extends never ? 'A' : 'B'
// Returns true if type is any, or false for any other type.
type IsStrictlyAny<T> =
UnionToIntersection<UnionForAny<T>> extends never ? true : false
type A = IsStrictlyAny<any> // true
type B = IsStrictlyAny<string> // false
type C = IsStrictlyAny<unknown> // false
```

Playground