## Issue

I’m trying to implement clamp for multiple number-ish types simultaneously like so:

```
import BigNumber from 'bignumber.js'
export const clamp = <T extends number | BigNumber>(min: typeof n, n: T, max: typeof n): T => {
if (isNumber(n)) {
return Math.max(min, Math.min(n, max)) as T
}
if (isBigNumber(n)) {
return BigNumber.max(min, BigNumber.min(n, max)) as T
}
}
const isNumber = (n: number | BigNumber): n is number => {
return typeof n === 'number'
}
const isBigNumber = (n: number | BigNumber): n is BigNumber => {
return n instanceof BigNumber
}
```

But code failes to compile with the following error:

```
TypeScript error in clamp.ts(5,21):
Argument of type 'number | BigNumber' is not assignable to parameter of type 'number'.
Type 'BigNumber' is not assignable to type 'number'. TS2345
3 | export const clamp = <T extends number | BigNumber>(min: typeof n, n: T, max: typeof n): T => {
4 | if (isNumber(n)) {
> 5 | return Math.max(min, Math.min(n, max)) as T
| ^
6 | }
7 |
8 | if (isBigNumber(n)) {
```

Shouldn’t types of `min`

and `max`

be inferred as `number`

on line 5? If not, how can one assure Typescript of correctness of types?

## Solution

Unfortunately this is one of the cases where Typescript’s type system comes short.

There is a proposal to allow intersection type guards, this would enable us to have a type guard such as:

```
const isNumber = (n: number | BigNumber, min: typeof n, max: typeof n): n is number & min is number & max is number => {
return typeof n === 'number';
}
```

Until such proposal is implemented, you’ll have to explicitly type-check both `min`

and `max`

variables:

```
import BigNumber from 'bignumber.js'
export const clamp = <T extends number | BigNumber>(min: T, n: T, max: T): number | BigNumber => {
if (isNumber(n) && isNumber(min) && isNumber(max)) {
return Math.max(min, Math.min(n, max));
}
if (isBigNumber(n) && isBigNumber(min) && isBigNumber(max)) {
return BigNumber.min(min, BigNumber.max(n, max));
}
throw new TypeError("Every parameter of this function must be either of type number or an instance of BigNumber");
}
const isNumber = (n: number | BigNumber): n is number => {
return typeof n === 'number'
}
const isBigNumber = (n: number | BigNumber): n is BigNumber => {
return n instanceof BigNumber
}
```

or cast both min and max:

```
import BigNumber from 'bignumber.js'
export const clamp = <T extends number | BigNumber>(min: T, n: T, max: T): number | BigNumber => {
if (isNumber(n)) {
return Math.max(min as number, Math.min(n, max as number));
}
return BigNumber.min(min as BigNumber, BigNumber.max(n, max as BigNumber));
}
const isNumber = (n: number | BigNumber): n is number => {
return typeof n === 'number'
}
```

Answered By – Joao Pedro Braz

Answer Checked By – Mary Flores (BugsFixing Volunteer)