diff --git a/index.d.ts b/index.d.ts index c8c021f36..952375bc6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -83,6 +83,7 @@ export type { NonNegativeInteger, IsNegative, } from './source/numeric'; +export type {IfNegative} from './source/if-negative'; export type {GreaterThan} from './source/greater-than'; export type {GreaterThanOrEqual} from './source/greater-than-or-equal'; export type {LessThan} from './source/less-than'; @@ -103,13 +104,16 @@ export type {WritableKeysOf} from './source/writable-keys-of'; export type {HasWritableKeys} from './source/has-writable-keys'; export type {Spread} from './source/spread'; export type {IsInteger} from './source/is-integer'; +export type {IfInteger} from './source/if-integer'; export type {IsFloat} from './source/is-float'; +export type {IfFloat} from './source/if-float'; export type {TupleToObject} from './source/tuple-to-object'; export type {TupleToUnion} from './source/tuple-to-union'; export type {UnionToTuple} from './source/union-to-tuple'; export type {IntRange} from './source/int-range'; export type {IntClosedRange} from './source/int-closed-range'; export type {IsEqual} from './source/is-equal'; +export type {IfEqual} from './source/if-equal'; export type { IsLiteral, IsStringLiteral, @@ -117,6 +121,13 @@ export type { IsBooleanLiteral, IsSymbolLiteral, } from './source/is-literal'; +export type { + IfLiteral, + IfStringLiteral, + IfNumericLiteral, + IfBooleanLiteral, + IfSymbolLiteral, +} from './source/if-literal'; export type {IsAny} from './source/is-any'; export type {IfAny} from './source/if-any'; export type {IsNever} from './source/is-never'; diff --git a/readme.md b/readme.md index e74c9572e..b72c225ab 100644 --- a/readme.md +++ b/readme.md @@ -191,7 +191,7 @@ Click the type names for complete docs. - [`WritableKeysOf`](source/writable-keys-of.d.ts) - Extract all writable (non-readonly) keys from the given type. - [`HasWritableKeys`](source/has-writable-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any writable fields. - [`Spread`](source/spread.d.ts) - Mimic the type inferred by TypeScript when merging two objects or two arrays/tuples using the spread syntax. -- [`IsEqual`](source/is-equal.d.ts) - Returns a boolean for whether the two given types are equal. +- [`IsEqual`](source/is-equal.d.ts) - Returns a boolean for whether the two given types are equal. (Conditional version: [`IfEqual`](source/if-equal.d.ts)) - [`TaggedUnion`](source/tagged-union.d.ts) - Create a union of types that share a common discriminant property. - [`IntRange`](source/int-range.d.ts) - Generate a union of numbers (includes the start and excludes the end). - [`IntClosedRange`](source/int-closed-range.d.ts) - Generate a union of numbers (includes the start and the end). @@ -239,11 +239,11 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>; //=> 'never' ``` -- [`IsLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). -- [`IsStringLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). -- [`IsNumericLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). -- [`IsBooleanLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). -- [`IsSymbolLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). +- [`IsLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). (Conditional version: [`IfLiteral`](source/if-literal.d.ts)) +- [`IsStringLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). (Conditional version: [`IfStringLiteral`](source/if-literal.d.ts)) +- [`IsNumericLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). (Conditional version: [`IfNumericLiteral`](source/if-literal.d.ts)) +- [`IsBooleanLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). (Conditional version: [`IfBooleanLiteral`](source/if-literal.d.ts)) +- [`IsSymbolLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). (Conditional version: [`IfSymbolLiteral`](source/if-literal.d.ts)) - [`IsAny`](source/is-any.d.ts) - Returns a boolean for whether the given type is `any`. (Conditional version: [`IfAny`](source/if-any.d.ts)) - [`IsNever`](source/is-never.d.ts) - Returns a boolean for whether the given type is `never`. (Conditional version: [`IfNever`](source/if-never.d.ts)) - [`IsUnknown`](source/is-unknown.d.ts) - Returns a boolean for whether the given type is `unknown`. (Conditional version: [`IfUnknown`](source/if-unknown.d.ts)) @@ -306,9 +306,9 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>; - [`NonNegative`](source/numeric.d.ts) - A non-negative `number`/`bigint` (`0 <= x < ∞`). - [`NegativeInteger`](source/numeric.d.ts) - A negative (`-∞ < x < 0`) `number` that is an integer. - [`NonNegativeInteger`](source/numeric.d.ts) - A non-negative (`0 <= x < ∞`) `number` that is an integer. -- [`IsNegative`](source/numeric.d.ts) - Returns a boolean for whether the given number is a negative number. -- [`IsFloat`](source/is-float.d.ts) - Returns a boolean for whether the given number is a float, like `1.5` or `-1.5`. -- [`IsInteger`](source/is-integer.d.ts) - Returns a boolean for whether the given number is a integer, like `-5`, `1.0` or `100`. +- [`IsNegative`](source/numeric.d.ts) - Returns a boolean for whether the given number is a negative number. (Conditional version: [`IfNegative`](source/if-negative.d.ts)) +- [`IsFloat`](source/is-float.d.ts) - Returns a boolean for whether the given number is a float, like `1.5` or `-1.5`. (Conditional version: [`IfFloat`](source/if-float.d.ts)) +- [`IsInteger`](source/is-integer.d.ts) - Returns a boolean for whether the given number is a integer, like `-5`, `1.0` or `100`. (Conditional version: [`IfInteger`](source/if-integer.d.ts)) - [`GreaterThan`](source/greater-than.d.ts) - Returns a boolean for whether a given number is greater than another number. - [`GreaterThanOrEqual`](source/greater-than-or-equal.d.ts) - Returns a boolean for whether a given number is greater than or equal to another number. - [`LessThan`](source/less-than.d.ts) - Returns a boolean for whether a given number is less than another number. diff --git a/source/if-equal.d.ts b/source/if-equal.d.ts new file mode 100644 index 000000000..92424adcb --- /dev/null +++ b/source/if-equal.d.ts @@ -0,0 +1,27 @@ +import type {IsEqual} from './is-equal'; + +/** +An if-else-like type that resolves depending on whether the two given types are equal. + +@see {@link IsEqual} + +@example +``` +import type {IfEqual} from 'type-fest'; + +type ShouldBeTrue = IfEqual; +//=> true + +type ShouldBeBar = IfEqual<'not', 'equal', 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities +*/ +export type IfEqual< + A, + B, + TypeIfEqual = true, + TypeIfNotEqual = false, +> = IsEqual extends true ? TypeIfEqual : TypeIfNotEqual; diff --git a/source/if-float.d.ts b/source/if-float.d.ts new file mode 100644 index 000000000..24ae9e7d6 --- /dev/null +++ b/source/if-float.d.ts @@ -0,0 +1,26 @@ +import type {IsFloat} from './is-float'; + +/** +An if-else-like type that resolves depending on whether the given type is a float, like `1.5` or `-1.5`. + +@see {@link IsFloat} + +@example +``` +import type {IfFloat} from 'type-fest'; + +type ShouldBeTrue = IfFloat<3.14>; +//=> true + +type ShouldBeBar = IfFloat<'not float', 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities +*/ +export type IfFloat< + T, + TypeIfFloat = true, + TypeIfNotFloat = false, +> = IsFloat extends true ? TypeIfFloat : TypeIfNotFloat; diff --git a/source/if-integer.d.ts b/source/if-integer.d.ts new file mode 100644 index 000000000..783837eca --- /dev/null +++ b/source/if-integer.d.ts @@ -0,0 +1,26 @@ +import type {IsInteger} from './is-integer'; + +/** +An if-else-like type that resolves depending on whether the given type is an integer, like `-5`, `1.0` or `100`. + +@see {@link IsInteger} + +@example +``` +import type {IfInteger} from 'type-fest'; + +type ShouldBeTrue = IfInteger<7>; +//=> true + +type ShouldBeBar = IfInteger<'not integer', 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities +*/ +export type IfInteger< + T, + TypeIfInteger = true, + TypeIfNotInteger = false, +> = IsInteger extends true ? TypeIfInteger : TypeIfNotInteger; diff --git a/source/if-literal.d.ts b/source/if-literal.d.ts new file mode 100644 index 000000000..ba83def8e --- /dev/null +++ b/source/if-literal.d.ts @@ -0,0 +1,126 @@ +import type {IsBooleanLiteral, IsLiteral, IsNumericLiteral, IsStringLiteral, IsSymbolLiteral} from './is-literal'; + +/** +An if-else-like type that resolves depending on whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). + +@see {@link IsStringLiteral} + +@example +``` +import type {IfStringLiteral} from 'type-fest'; + +type ShouldBeTrue = IfStringLiteral<'string'>; +//=> true + +type ShouldBeBar = IfStringLiteral; +//=> 'bar' +``` + +@category Type Guard +@category Utilities + */ +export type IfStringLiteral< + T, + TypeIfStringLiteral = true, + TypeIfNotStringLiteral = false, +> = IsStringLiteral extends true ? TypeIfStringLiteral : TypeIfNotStringLiteral; + +/** +An if-else-like type that resolves depending on whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). + +@see {@link IsNumericLiteral} + +@example +``` +import type {IfNumericLiteral} from 'type-fest'; + +type ShouldBeTrue = IfNumericLiteral<1>; +//=> true + +type ShouldBeBar = IfNumericLiteral<'not numeric', 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities + */ +export type IfNumericLiteral< + T, + TypeIfNumericLiteral = true, + TypeIfNotNumericLiteral = false, +> = IsNumericLiteral extends true ? TypeIfNumericLiteral : TypeIfNotNumericLiteral; + +/** +An if-else-like type that resolves depending on whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). + +@see {@link IsBooleanLiteral} + +@example +``` +import type {IfBooleanLiteral} from 'type-fest'; + +type ShouldBeTrue = IfBooleanLiteral; +//=> true + +type ShouldBeBar = IfBooleanLiteral<'not boolean', 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities + */ +export type IfBooleanLiteral< + T, + TypeIfBooleanLiteral = true, + TypeIfNotBooleanLiteral = false, +> = IsBooleanLiteral extends true ? TypeIfBooleanLiteral : TypeIfNotBooleanLiteral; + +/** +An if-else-like type that resolves depending on whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). + +@see {@link IsSymbolLiteral} + +@example +``` +import type {IfSymbolLiteral} from 'type-fest'; + +type ShouldBeTrue = IfSymbolLiteral; +//=> true + +type ShouldBeBar = IfSymbolLiteral<'not symbol', 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities + */ +export type IfSymbolLiteral< + T, + TypeIfSymbolLiteral = true, + TypeIfNotSymbolLiteral = false, +> = IsSymbolLiteral extends true ? TypeIfSymbolLiteral : TypeIfNotSymbolLiteral; + +/** +An if-else-like type that resolves depending on whether the given type is a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types). + +@see {@link IsLiteral} + +@example +``` +import type {IfLiteral} from 'type-fest'; + +type ShouldBeTrue = IfLiteral<"literal">; +//=> true + +type ShouldBeBar = IfLiteral<{}, 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities + */ +export type IfLiteral< + T, + TypeIfLiteral = true, + TypeIfNotLiteral = false, +> = IsLiteral extends true ? TypeIfLiteral : TypeIfNotLiteral; diff --git a/source/if-negative.d.ts b/source/if-negative.d.ts new file mode 100644 index 000000000..e50dc64d2 --- /dev/null +++ b/source/if-negative.d.ts @@ -0,0 +1,26 @@ +import type {IsNegative, Numeric} from './numeric'; + +/** +An if-else-like type that resolves depending on whether the given number is a negative number, like `-80` or `-0.123`. + +@see {@link IsNegative} + +@example +``` +import type {IfNegative} from 'type-fest'; + +type ShouldBeTrue = IfNegative<-80>; +//=> true + +type ShouldBeBar = IfNegative<0.123, 'foo', 'bar'>; +//=> 'bar' +``` + +@category Type Guard +@category Utilities +*/ +export type IfNegative< + T extends Numeric, + TypeIfNegative = true, + TypeIfNotNegative = false, +> = IsNegative extends true ? TypeIfNegative : TypeIfNotNegative; diff --git a/test-d/if-equal.ts b/test-d/if-equal.ts new file mode 100644 index 000000000..bbd5e4f0c --- /dev/null +++ b/test-d/if-equal.ts @@ -0,0 +1,16 @@ +import {expectType} from 'tsd'; +import type {IfEqual} from '../index'; + +// `IfEqual` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// Missing all generic parameters. +// @ts-expect-error +type A = IfEqual; + +// Missing `Y` generic parameter. +// @ts-expect-error +type B = IfEqual; diff --git a/test-d/if-float.ts b/test-d/if-float.ts new file mode 100644 index 000000000..c284bc6a1 --- /dev/null +++ b/test-d/if-float.ts @@ -0,0 +1,12 @@ +import {expectType} from 'tsd'; +import type {IfFloat} from '../index'; + +// `IfFloat` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// Missing generic parameter +// @ts-expect-error +type A = IfFloat; diff --git a/test-d/if-integer.ts b/test-d/if-integer.ts new file mode 100644 index 000000000..53884cb9b --- /dev/null +++ b/test-d/if-integer.ts @@ -0,0 +1,12 @@ +import {expectType} from 'tsd'; +import type {IfInteger} from '../index'; + +// `IfInteger` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// Missing generic parameter +// @ts-expect-error +type A = IfInteger; diff --git a/test-d/if-literal.ts b/test-d/if-literal.ts new file mode 100644 index 000000000..4bdef7f78 --- /dev/null +++ b/test-d/if-literal.ts @@ -0,0 +1,45 @@ +import {expectType} from 'tsd'; +import type {IfLiteral, IfStringLiteral, IfNumericLiteral, IfBooleanLiteral, IfSymbolLiteral} from '../index'; + +// `IfLiteral` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// `IfStringLiteral` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// `IfNumericLiteral` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// `IfBooleanLiteral` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// `IfSymbolLiteral` should return `true`/`false` if only `T` is specified +const symbolLiteral = Symbol(''); +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// Missing generic parameter +// @ts-expect-error +type A0 = IfLiteral; +// @ts-expect-error +type A1 = IfStringLiteral; +// @ts-expect-error +type A2 = IfNumericLiteral; +// @ts-expect-error +type A3 = IfBooleanLiteral; +// @ts-expect-error +type A4 = IfSymbolLiteral; diff --git a/test-d/if-negative.ts b/test-d/if-negative.ts new file mode 100644 index 000000000..dab0e1966 --- /dev/null +++ b/test-d/if-negative.ts @@ -0,0 +1,12 @@ +import {expectType} from 'tsd'; +import type {IfNegative} from '../index'; + +// `IfNegative` should return `true`/`false` if only `T` is specified +expectType>(true); +expectType>(false); +expectType>('T'); +expectType>('F'); + +// Missing generic parameter +// @ts-expect-error +type A = IfNegative;