Skip to content

Commit 21a92f6

Browse files
lvltesindresorhussom-sm
authored
IsFloat / IsInteger: Fix instantiations with numbers represented using exponential notation (#1101)
Co-authored-by: Sindre Sorhus <[email protected]> Co-authored-by: Som Shekhar Mukherjee <[email protected]>
1 parent 6db45e2 commit 21a92f6

File tree

4 files changed

+91
-56
lines changed

4 files changed

+91
-56
lines changed

source/is-float.d.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,41 @@ import type {Zero} from './numeric';
33
/**
44
Returns a boolean for whether the given number is a float, like `1.5` or `-1.5`.
55
6-
It returns `false` for `Infinity`.
7-
86
Use-case:
97
- If you want to make a conditional branch based on the result of whether a number is a float or not.
108
119
@example
1210
```
13-
type Float = IsFloat<1.5>;
11+
import type {IsFloat, PositiveInfinity} from "type-fest";
12+
13+
type A = IsFloat<1.5>;
1414
//=> true
1515
16-
type IntegerWithDecimal = IsInteger<1.0>;
17-
//=> false
16+
type B = IsFloat<-1.5>;
17+
//=> true
1818
19-
type NegativeFloat = IsInteger<-1.5>;
19+
type C = IsFloat<1e-7>;
2020
//=> true
2121
22-
type Infinity_ = IsInteger<Infinity>;
22+
type D = IsFloat<1.0>;
23+
//=> false
24+
25+
type E = IsFloat<PositiveInfinity>;
26+
//=> false
27+
28+
type F = IsFloat<1.23e+21>;
2329
//=> false
2430
```
31+
32+
@category Type Guard
33+
@category Numeric
2534
*/
26-
export type IsFloat<T> =
27-
T extends number
28-
? `${T}` extends `${infer _Sign extends '' | '-'}${number}.${infer Decimal extends number}`
29-
? Decimal extends Zero
30-
? false
31-
: true
32-
: false
35+
export type IsFloat<T> = T extends number
36+
? `${T}` extends `${number}e${infer E extends '-' | '+'}${number}`
37+
? E extends '-'
38+
? true
39+
: false
40+
: `${T}` extends `${number}.${number}`
41+
? true
42+
: false
3343
: false;

source/is-integer.d.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,48 @@ import type {IsFloat} from './is-float';
33
import type {PositiveInfinity, NegativeInfinity} from './numeric';
44

55
/**
6-
Returns a boolean for whether the given number is a integer, like `-5`, `1.0` or `100`.
7-
8-
Like [`Number#IsInteger()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/IsInteger) but for types.
6+
Returns a boolean for whether the given number is an integer, like `-5`, `1.0`, or `100`.
97
108
Use-case:
11-
- If you want to make a conditional branch based on the result of whether a number is a intrger or not.
9+
- If you want to make a conditional branch based on the result of whether a number is an integer or not.
1210
1311
@example
1412
```
15-
type Integer = IsInteger<1>;
16-
//=> true
13+
import type {IsInteger, PositiveInfinity} from "type-fest";
1714
18-
type IntegerWithDecimal = IsInteger<1.0>;
15+
type A = IsInteger<1>;
1916
//=> true
2017
21-
type NegativeInteger = IsInteger<-1>;
18+
type B = IsInteger<1.0>;
2219
//=> true
2320
24-
type Float = IsInteger<1.5>;
25-
//=> false
21+
type C = IsInteger<-1>;
22+
//=> true
2623
27-
// Supports non-decimal numbers
24+
type D = IsInteger<0b10>;
25+
//=> true
2826
29-
type OctalInteger: IsInteger<0o10>;
27+
type E = IsInteger<0o10>;
3028
//=> true
3129
32-
type BinaryInteger: IsInteger<0b10>;
30+
type F = IsInteger<0x10>;
3331
//=> true
3432
35-
type HexadecimalInteger: IsInteger<0x10>;
33+
type G = IsInteger<1.23+21>;
3634
//=> true
35+
36+
type H = IsInteger<1.5>;
37+
//=> false
38+
39+
type I = IsInteger<PositiveInfinity>;
40+
//=> false
41+
42+
type J = IsInteger<1e-7>;
43+
//=> false
3744
```
45+
46+
@category Type Guard
47+
@category Numeric
3848
*/
3949
export type IsInteger<T> =
4050
T extends bigint

test-d/is-float.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
import {expectType} from 'tsd';
22
import type {IsFloat, PositiveInfinity} from '../index';
33

4-
expectType<false>({} as IsFloat<0>);
5-
expectType<false>({} as IsFloat<1>);
6-
expectType<false>({} as IsFloat<1.0>); // eslint-disable-line unicorn/no-zero-fractions
7-
expectType<true>({} as IsFloat<1.5>);
8-
expectType<false>({} as IsFloat<-1>);
9-
expectType<false>({} as IsFloat<number>);
10-
expectType<false>({} as IsFloat<0o10>);
11-
expectType<false>({} as IsFloat<1n>);
12-
expectType<false>({} as IsFloat<0n>);
13-
expectType<false>({} as IsFloat<0b10>);
14-
expectType<false>({} as IsFloat<0x10>);
15-
expectType<false>({} as IsFloat<1e+100>);
16-
expectType<false>({} as IsFloat<PositiveInfinity>);
17-
expectType<false>({} as IsFloat<typeof Number.POSITIVE_INFINITY>);
4+
declare const x: unknown;
5+
6+
expectType<true>(x as IsFloat<1.5>);
7+
expectType<true>(x as IsFloat<999_999_999_999_999.9>);
8+
expectType<true>(x as IsFloat<0.000_000_1>);
9+
expectType<true>(x as IsFloat<-1e-7>);
10+
11+
expectType<false>(x as IsFloat<0>);
12+
expectType<false>(x as IsFloat<1>);
13+
expectType<false>(x as IsFloat<1.0>); // eslint-disable-line unicorn/no-zero-fractions
14+
expectType<false>(x as IsFloat<-1>);
15+
expectType<false>(x as IsFloat<number>);
16+
expectType<false>(x as IsFloat<0o10>);
17+
expectType<false>(x as IsFloat<1n>);
18+
expectType<false>(x as IsFloat<0n>);
19+
expectType<false>(x as IsFloat<0b10>);
20+
expectType<false>(x as IsFloat<0x10>);
21+
expectType<false>(x as IsFloat<1e+100>);
22+
expectType<false>(x as IsFloat<1.23e+21>);
23+
expectType<false>(x as IsFloat<-1.23e+21>);
24+
expectType<false>(x as IsFloat<'1.23'>);
25+
expectType<false>(x as IsFloat<PositiveInfinity>);

test-d/is-integer.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
import {expectType} from 'tsd';
22
import type {IsInteger, PositiveInfinity} from '../index';
33

4-
expectType<true>({} as IsInteger<0>);
5-
expectType<true>({} as IsInteger<1>);
6-
expectType<true>({} as IsInteger<1.0>); // eslint-disable-line unicorn/no-zero-fractions
7-
expectType<false>({} as IsInteger<1.5>);
8-
expectType<true>({} as IsInteger<-1>);
9-
expectType<false>({} as IsInteger<number>);
10-
expectType<true>({} as IsInteger<0o10>);
11-
expectType<true>({} as IsInteger<1n>);
12-
expectType<true>({} as IsInteger<0n>);
13-
expectType<true>({} as IsInteger<0b10>);
14-
expectType<true>({} as IsInteger<0x10>);
15-
expectType<true>({} as IsInteger<1e+100>);
16-
expectType<false>({} as IsInteger<PositiveInfinity>);
17-
expectType<false>({} as IsInteger<typeof Number.POSITIVE_INFINITY>);
4+
declare const x: unknown;
5+
6+
expectType<true>(x as IsInteger<0>);
7+
expectType<true>(x as IsInteger<1>);
8+
expectType<true>(x as IsInteger<1.0>); // eslint-disable-line unicorn/no-zero-fractions
9+
expectType<true>(x as IsInteger<-1>);
10+
expectType<true>(x as IsInteger<0o10>);
11+
expectType<true>(x as IsInteger<1n>);
12+
expectType<true>(x as IsInteger<0n>);
13+
expectType<true>(x as IsInteger<0b10>);
14+
expectType<true>(x as IsInteger<0x10>);
15+
expectType<true>(x as IsInteger<1e+100>);
16+
expectType<true>(x as IsInteger<1.23e+21>);
17+
expectType<true>(x as IsInteger<-1.23e+21>);
18+
19+
expectType<false>(x as IsInteger<1.5>);
20+
expectType<false>(x as IsInteger<-1.5>);
21+
expectType<false>(x as IsInteger<number>);
22+
expectType<false>(x as IsInteger<PositiveInfinity>);
23+
expectType<false>(x as IsInteger<0.000_000_1>);
24+
expectType<false>(x as IsInteger<-1e-7>);

0 commit comments

Comments
 (0)