vtils
Version:
一个面向业务的 JavaScript/TypeScript 实用程序库。
1,821 lines (1,453 loc) • 143 kB
TypeScript
/**
* 类型工具库。
*
* @packageDocumentation
*/
import type { BuildTuple } from './internal';
import type { BuiltIns } from './internal';
import type { HasMultipleCallSignatures } from './internal';
import type { HomomorphicPick } from './internal';
import type { IfArrayReadonly } from './internal';
import type { IsLowerCase } from './internal';
import type { IsNumberLike } from './internal';
import type { IsNumeric } from './internal';
import type { IsUpperCase } from './internal';
import type { NonRecursiveType } from './internal';
import type { Not } from './internal';
import type { NumberAbsolute } from './internal';
import type { PositiveNumericStringGt } from './internal';
import type { RequireNone } from './internal';
import type { StaticPartOfArray } from './internal';
import type { StringToNumber } from './internal';
import type { ToString } from './internal';
import type { TupleMax } from './internal';
import type { TupleMin } from './internal';
import type { UpperCaseCharacters } from './internal';
import type { VariablePartOfArray } from './internal';
import type { WordSeparators } from './internal';
/**
Returns a boolean for whether two given types are both true.
Use-case: Constructing complex conditional types where multiple conditions must be satisfied.
@example
```
import type {And} from 'type-fest';
And<true, true>;
//=> true
And<true, false>;
//=> false
```
@see {@link Or}
*/
declare type And<A extends boolean, B extends boolean> = [A, B][number] extends true
? true
: true extends [IsEqual<A, false>, IsEqual<B, false>][number]
? false
: never;
declare type AnyArray_2<T = any> = Array<T> | ReadonlyArray<T>;
export { AnyArray_2 as AnyArray }
/**
* 任意异步函数。
*
* @public
*/
export declare type AnyAsyncFunction = Record<any, any> & {
(...args: any[]): Promise<any>;
};
/**
* 任意函数。
*
* @public
*/
declare type AnyFunction_2 = Record<any, any> & {
(...args: any[]): any;
};
export { AnyFunction_2 as AnyFunction }
/**
* 任意对象。
*
* @public
*/
declare type AnyObject_2 = Record<any, any>;
export { AnyObject_2 as AnyObject }
/**
Methods to exclude.
*/
declare type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift';
declare type AsyncFunction = (...arguments_: any[]) => Promise<unknown>;
/**
Create an async version of the given function type, by boxing the return type in `Promise` while keeping the same parameter types.
Use-case: You have two functions, one synchronous and one asynchronous that do the same thing. Instead of having to duplicate the type definition, you can use `Asyncify` to reuse the synchronous type.
@example
```
import type {Asyncify} from 'type-fest';
// Synchronous function.
function getFooSync(someArg: SomeType): Foo {
// …
}
type AsyncifiedFooGetter = Asyncify<typeof getFooSync>;
//=> type AsyncifiedFooGetter = (someArg: SomeType) => Promise<Foo>;
// Same as `getFooSync` but asynchronous.
const getFooAsync: AsyncifiedFooGetter = (someArg) => {
// TypeScript now knows that `someArg` is `SomeType` automatically.
// It also knows that this function must return `Promise<Foo>`.
// If you have `@typescript-eslint/promise-function-async` linter rule enabled, it will even report that "Functions that return promises must be async.".
// …
}
```
@category Async
*/
export declare type Asyncify<Function_ extends (...arguments_: any[]) => any> = SetReturnType<Function_, Promise<Awaited<ReturnType<Function_>>>>;
/** Useful as a return type in interfaces or abstract classes with missing implementation */
export declare type AsyncOrSync<T> = PromiseLike<T> | T;
/**
Unwrap the return type of a function that returns a `Promise`.
There has been [discussion](https://github.com/microsoft/TypeScript/pull/35998) about implementing this type in TypeScript.
@example
```ts
import type {AsyncReturnType} from 'type-fest';
import {asyncFunction} from 'api';
// This type resolves to the unwrapped return type of `asyncFunction`.
type Value = AsyncReturnType<typeof asyncFunction>;
async function doSomething(value: Value) {}
asyncFunction().then(value => doSomething(value));
```
@category Async
*/
export declare type AsyncReturnType<Target extends AsyncFunction> = Awaited<ReturnType<Target>>;
/** Combination of DeepPartial and DeepWritable */
export declare type Buildable<T> = PartialDeep<WritableDeep<T>>;
declare type Builtin = Primitive_2 | Function | Date | Error | RegExp;
/**
Matches any primitive, `void`, `Date`, or `RegExp` value.
*/
declare type BuiltIns_2 = Primitive | void | Date | RegExp;
/**
Convert a string literal to camel-case.
This can be useful when, for example, converting some kebab-cased command-line flags or a snake-cased database result.
By default, consecutive uppercase letter are preserved. See {@link CamelCaseOptions.preserveConsecutiveUppercase preserveConsecutiveUppercase} option to change this behaviour.
@example
```
import type {CamelCase} from 'type-fest';
// Simple
const someVariable: CamelCase<'foo-bar'> = 'fooBar';
// Advanced
type CamelCasedProperties<T> = {
[K in keyof T as CamelCase<K>]: T[K]
};
interface RawOptions {
'dry-run': boolean;
'full_family_name': string;
foo: number;
BAR: string;
QUZ_QUX: number;
'OTHER-FIELD': boolean;
}
const dbResult: CamelCasedProperties<RawOptions> = {
dryRun: true,
fullFamilyName: 'bar.js',
foo: 123,
bar: 'foo',
quzQux: 6,
otherField: false
};
```
@category Change case
@category Template literal
*/
export declare type CamelCase<Type, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = Type extends string
? string extends Type
? Type
: Uncapitalize<CamelCaseFromArray<Words<Type extends Uppercase<Type> ? Lowercase<Type> : Type>, Options>>
: Type;
/**
Convert an array of words to camel-case.
*/
declare type CamelCaseFromArray<
Words extends string[],
Options extends CamelCaseOptions,
OutputString extends string = '',
> = Words extends [
infer FirstWord extends string,
...infer RemainingWords extends string[],
]
? Options['preserveConsecutiveUppercase'] extends true
? `${Capitalize<FirstWord>}${CamelCaseFromArray<RemainingWords, Options>}`
: `${Capitalize<Lowercase<FirstWord>>}${CamelCaseFromArray<RemainingWords, Options>}`
: OutputString;
/**
CamelCase options.
@see {@link CamelCase}
*/
declare type CamelCaseOptions = {
/**
Whether to preserved consecutive uppercase letter.
@default true
*/
preserveConsecutiveUppercase?: boolean;
};
/**
Matches a [`class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
@category Class
*/
export declare type Class<T, Arguments extends unknown[] = any[]> = {
prototype: Pick<T, keyof T>;
new(...arguments_: Arguments): T;
};
/**
Recursively simplifies a type while including and/or excluding certain types from being simplified.
This type is **experimental** and was introduced as a result of this {@link https://github.com/sindresorhus/type-fest/issues/436 issue}. It should be used with caution.
See {@link ConditionalSimplify} for usages and examples.
@internal
@experimental
@category Object
*/
declare type ConditionalSimplifyDeep<Type, ExcludeType = never, IncludeType = unknown> = Type extends ExcludeType
? Type
: Type extends IncludeType
? {[TypeKey in keyof Type]: ConditionalSimplifyDeep<Type[TypeKey], ExcludeType, IncludeType>}
: Type;
/**
Convert a string literal to screaming-snake-case.
This can be useful when, for example, converting a camel-cased object property to a screaming-snake-cased SQL column name.
@example
```
import type {ScreamingSnakeCase} from 'type-fest';
const someVariable: ScreamingSnakeCase<'fooBar'> = 'FOO_BAR';
```
@category Change case
@category Template literal
*/
export declare type ConstantCase<Value> = Value extends string
? IsScreamingSnakeCase<Value> extends true
? Value
: Uppercase<SnakeCase<Value>>
: Value;
declare type DeepOmitModify<T> =
| {
[K in keyof T]: T[K] extends never ? any : T[K] extends object ? DeepOmitModify<T[K]> : never;
}
| Array<DeepOmitModify<T>>
| Promise<DeepOmitModify<T>>
| Set<DeepOmitModify<T>>
| ReadonlySet<DeepOmitModify<T>>
| WeakSet<DeepOmitModify<T>>
| Map<any, DeepOmitModify<T>>
| WeakMap<any, DeepOmitModify<T>>;
declare type DefaultPathsOptions = {
maxRecursionDepth: 10;
bracketNotation: false;
leavesOnly: false;
depth: number;
};
/**
* 去除类型 T 中的 undefined。
*
* @public
* @example
* ```typescript
* type X = string | undefined
* type Y = Defined<X> // => string
* ```
*/
export declare type Defined<T> = Exclude<T, undefined>;
/**
Convert a string literal to a custom string delimiter casing.
This can be useful when, for example, converting a camel-cased object property to an oddly cased one.
@see KebabCase
@see SnakeCase
@example
```
import type {DelimiterCase} from 'type-fest';
// Simple
const someVariable: DelimiterCase<'fooBar', '#'> = 'foo#bar';
// Advanced
type OddlyCasedProperties<T> = {
[K in keyof T as DelimiterCase<K, '#'>]: T[K]
};
interface SomeOptions {
dryRun: boolean;
includeFile: string;
foo: number;
}
const rawCliOptions: OddlyCasedProperties<SomeOptions> = {
'dry#run': true,
'include#file': 'bar.js',
foo: 123
};
```
@category Change case
@category Template literal
*/
export declare type DelimiterCase<Value, Delimiter extends string> = string extends Value ? Value : Value extends string
? StringArrayToDelimiterCase<
SplitIncludingDelimiters<Value, WordSeparators | UpperCaseCharacters>,
true,
WordSeparators,
UpperCaseCharacters,
Delimiter
>
: Value;
export declare type DotPath<T> = object extends T ? string : T extends any[] ? '0' | SubKeys<T, 0> : T extends readonly any[] ? Extract<keyof T, `${number}`> | SubKeys<T, Extract<keyof T, `${number}`>> : T extends object ? Extract<keyof T, string> | SubKeys<T, Extract<keyof T, string>> : never;
export declare type DotPathValue<T, Path extends string> = Path extends '0' ? T[0] : Path extends keyof T ? T[Path] : Path extends `${infer K}.${infer R}` ? K extends '0' ? DotPathValue<T[0], R> : K extends keyof T ? DotPathValue<T[K], R> : unknown : unknown;
export declare type DotPathWithRoot<T> = DotPath<T> | '.';
export declare type DotPathWithRootValue<T, Path extends string> = Path extends '.' ? T : DotPathValue<T, Path>;
/** Easily extract the type of a given array's elements */
export declare type ElementOf<T extends readonly any[]> = T extends readonly (infer ET)[] ? ET : never;
/**
Represents a strictly empty plain object, the `{}` value.
When you annotate something as the type `{}`, it can be anything except `null` and `undefined`. This means that you cannot use `{}` to represent an empty plain object ([read more](https://stackoverflow.com/questions/47339869/typescript-empty-object-and-any-difference/52193484#52193484)).
@example
```
import type {EmptyObject} from 'type-fest';
// The following illustrates the problem with `{}`.
const foo1: {} = {}; // Pass
const foo2: {} = []; // Pass
const foo3: {} = 42; // Pass
const foo4: {} = {a: 1}; // Pass
// With `EmptyObject` only the first case is valid.
const bar1: EmptyObject = {}; // Pass
const bar2: EmptyObject = 42; // Fail
const bar3: EmptyObject = []; // Fail
const bar4: EmptyObject = {a: 1}; // Fail
```
Unfortunately, `Record<string, never>`, `Record<keyof any, never>` and `Record<never, never>` do not work. See {@link https://github.com/sindresorhus/type-fest/issues/395 #395}.
@category Object
*/
declare type EmptyObject = {[emptyObjectSymbol]?: never};
declare const emptyObjectSymbol: unique symbol;
/**
Create a type from an object type without certain keys.
We recommend setting the `requireExactProps` option to `true`.
This type is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html#the-omit-helper-type). The `Omit` type does not restrict the omitted keys to be keys present on the given type, while `Except` does. The benefits of a stricter type are avoiding typos and allowing the compiler to pick up on rename refactors automatically.
This type was proposed to the TypeScript team, which declined it, saying they prefer that libraries implement stricter versions of the built-in types ([microsoft/TypeScript#30825](https://github.com/microsoft/TypeScript/issues/30825#issuecomment-523668235)).
@example
```
import type {Except} from 'type-fest';
type Foo = {
a: number;
b: string;
};
type FooWithoutA = Except<Foo, 'a'>;
//=> {b: string}
const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
//=> errors: 'a' does not exist in type '{ b: string; }'
type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
//=> {a: number} & Partial<Record<"b", never>>
const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
//=> errors at 'b': Type 'string' is not assignable to type 'undefined'.
// The `Omit` utility type doesn't work when omitting specific keys from objects containing index signatures.
// Consider the following example:
type UserData = {
[metadata: string]: string;
email: string;
name: string;
role: 'admin' | 'user';
};
// `Omit` clearly doesn't behave as expected in this case:
type PostPayload = Omit<UserData, 'email'>;
//=> type PostPayload = { [x: string]: string; [x: number]: string; }
// In situations like this, `Except` works better.
// It simply removes the `email` key while preserving all the other keys.
type PostPayload = Except<UserData, 'email'>;
//=> type PostPayload = { [x: string]: string; name: string; role: 'admin' | 'user'; }
```
@category Object
*/
declare type Except<ObjectType, KeysType extends keyof ObjectType, Options extends ExceptOptions = {requireExactProps: false}> = {
[KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType];
} & (Options['requireExactProps'] extends true
? Partial<Record<KeysType, never>>
: {});
declare type ExceptOptions = {
/**
Disallow assigning non-specified properties.
Note that any omitted properties in the resulting type will be present in autocomplete as `undefined`.
@default false
*/
requireExactProps?: boolean;
};
declare type ExcludeUndefined<T> = Exclude<T, undefined>;
/**
Filter out keys from an object.
Returns `never` if `Exclude` is strictly equal to `Key`.
Returns `never` if `Key` extends `Exclude`.
Returns `Key` otherwise.
@example
```
type Filtered = Filter<'foo', 'foo'>;
//=> never
```
@example
```
type Filtered = Filter<'bar', string>;
//=> never
```
@example
```
type Filtered = Filter<'bar', 'foo'>;
//=> 'bar'
```
@see {Except}
*/
declare type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true ? never : (KeyType extends ExcludeType ? never : KeyType);
/**
A finite `number`.
You can't pass a `bigint` as they are already guaranteed to be finite.
Use-case: Validating and documenting parameters.
Note: This can't detect `NaN`, please upvote [this issue](https://github.com/microsoft/TypeScript/issues/28682) if you want to have this type as a built-in in TypeScript.
@example
```
import type {Finite} from 'type-fest';
declare function setScore<T extends number>(length: Finite<T>): void;
```
@category Numeric
*/
export declare type Finite<T extends number> = T extends PositiveInfinity | NegativeInfinity ? never : T;
/**
* 返回函数 T 第一个参数的类型。
*
* @public
* @example
* ```typescript
* type F = (x: string, y: number) => any
* type X = FirstParameter<F> // => string
* ```
*/
export declare type FirstParameter<T extends (...args: any[]) => any> = Head<Parameters<T>>;
/**
Create a type that represents an array of the given type and length. The array's length and the `Array` prototype methods that manipulate its length are excluded in the resulting type.
Please participate in [this issue](https://github.com/microsoft/TypeScript/issues/26223) if you want to have a similar type built into TypeScript.
Use-cases:
- Declaring fixed-length tuples or arrays with a large number of items.
- Creating a range union (for example, `0 | 1 | 2 | 3 | 4` from the keys of such a type) without having to resort to recursive types.
- Creating an array of coordinates with a static length, for example, length of 3 for a 3D vector.
Note: This type does not prevent out-of-bounds access. Prefer `ReadonlyTuple` unless you need mutability.
@example
```
import type {FixedLengthArray} from 'type-fest';
type FencingTeam = FixedLengthArray<string, 3>;
const guestFencingTeam: FencingTeam = ['Josh', 'Michael', 'Robert'];
const homeFencingTeam: FencingTeam = ['George', 'John'];
//=> error TS2322: Type string[] is not assignable to type 'FencingTeam'
guestFencingTeam.push('Sam');
//=> error TS2339: Property 'push' does not exist on type 'FencingTeam'
```
@category Array
@see ReadonlyTuple
*/
export declare type FixedLengthArray<Element, Length extends number, ArrayPrototype = [Element, ...Element[]]> = Pick<
ArrayPrototype,
Exclude<keyof ArrayPrototype, ArrayLengthMutationKeys>
> & {
[index: number]: Element;
[Symbol.iterator]: () => IterableIterator<Element>;
readonly length: Length;
};
/**
Returns a boolean for whether a given number is greater than another number.
@example
```
import type {GreaterThan} from 'type-fest';
GreaterThan<1, -5>;
//=> true
GreaterThan<1, 1>;
//=> false
GreaterThan<1, 5>;
//=> false
```
*/
declare type GreaterThan<A extends number, B extends number> = number extends A | B
? never
: [
IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
] extends infer R extends [boolean, boolean, boolean, boolean]
? Or<
And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
And<IsEqual<R[3], true>, IsEqual<R[1], false>>
> extends true
? true
: Or<
And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
And<IsEqual<R[2], true>, IsEqual<R[0], false>>
> extends true
? false
: true extends R[number]
? false
: [IsNegative<A>, IsNegative<B>] extends infer R extends [boolean, boolean]
? [true, false] extends R
? false
: [false, true] extends R
? true
: [false, false] extends R
? PositiveNumericStringGt<`${A}`, `${B}`>
: PositiveNumericStringGt<`${NumberAbsolute<B>}`, `${NumberAbsolute<A>}`>
: never
: never;
/**
Returns a boolean for whether a given number is greater than or equal to another number.
@example
```
import type {GreaterThanOrEqual} from 'type-fest';
GreaterThanOrEqual<1, -5>;
//=> true
GreaterThanOrEqual<1, 1>;
//=> true
GreaterThanOrEqual<1, 5>;
//=> false
```
*/
declare type GreaterThanOrEqual<A extends number, B extends number> = number extends A | B
? never
: A extends B ? true : GreaterThan<A, B>;
/** Functional programming essentials */
export declare type Head<T extends AnyArray_2> = T["length"] extends 0 ? never : T[0];
/**
Returns a boolean for whether the given array includes the given item.
This can be useful if another type wants to make a decision based on whether the array includes that item.
@example
```
import type {Includes} from 'type-fest';
type hasRed<array extends any[]> = Includes<array, 'red'>;
```
@category Array
*/
declare type Includes<Value extends readonly any[], Item> =
Value extends readonly [Value[0], ...infer rest]
? IsEqual<Value[0], Item> extends true
? true
: Includes<rest, Item>
: false;
/**
A `number` that is an integer.
Use-case: Validating and documenting parameters.
@example
```
type Integer = Integer<1>;
//=> 1
type IntegerWithDecimal = Integer<1.0>;
//=> 1
type NegativeInteger = Integer<-1>;
//=> -1
type Float = Integer<1.5>;
//=> never
// Supports non-decimal numbers
type OctalInteger: Integer<0o10>;
//=> 0o10
type BinaryInteger: Integer<0b10>;
//=> 0b10
type HexadecimalInteger: Integer<0x10>;
//=> 0x10
```
@example
```
import type {Integer} from 'type-fest';
declare function setYear<T extends number>(length: Integer<T>): void;
```
@see NegativeInteger
@see NonNegativeInteger
@category Numeric
*/
// `${bigint}` is a type that matches a valid bigint literal without the `n` (ex. 1, 0b1, 0o1, 0x1)
// Because T is a number and not a string we can effectively use this to filter out any numbers containing decimal points
export declare type Integer<T> =
T extends unknown // To distributive type
? IsInteger<T> extends true ? T : never
: never;
declare type InternalPaths<T, Options extends Required<PathsOptions>> =
Options['maxRecursionDepth'] extends infer MaxDepth extends number
? Required<T> extends infer T
? T extends EmptyObject | readonly []
? never
: {
[Key in keyof T]:
Key extends string | number // Limit `Key` to string or number.
? (
Options['bracketNotation'] extends true
? IsNumberLike<Key> extends true
? `[${Key}]`
: (Key | ToString<Key>)
: never
|
Options['bracketNotation'] extends false
// If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
? (Key | ToString<Key>)
: never
) extends infer TranformedKey extends string | number ?
// 1. If style is 'a[0].b' and 'Key' is a numberlike value like 3 or '3', transform 'Key' to `[${Key}]`, else to `${Key}` | Key
// 2. If style is 'a.0.b', transform 'Key' to `${Key}` | Key
| ((Options['leavesOnly'] extends true
? MaxDepth extends 0
? TranformedKey
: T[Key] extends EmptyObject | readonly [] | NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
? TranformedKey
: never
: TranformedKey
) extends infer _TransformedKey
// If `depth` is provided, the condition becomes truthy only when it reaches `0`.
// Otherwise, since `depth` defaults to `number`, the condition is always truthy, returning paths at all depths.
? 0 extends Options['depth']
? _TransformedKey
: never
: never)
| (
// Recursively generate paths for the current key
GreaterThan<MaxDepth, 0> extends true // Limit the depth to prevent infinite recursion
? _Paths<T[Key],
{
bracketNotation: Options['bracketNotation'];
maxRecursionDepth: Subtract<MaxDepth, 1>;
leavesOnly: Options['leavesOnly'];
depth: Options['depth'] extends infer Depth extends number // For distributing `Options['depth']`
? Depth extends 0 // Don't subtract further if `Depth` has reached `0`
? never
: ToString<Depth> extends `-${number}` // Don't subtract if `Depth` is -ve
? never
: Subtract<Options['depth'], 1> // If `Subtract` supported -ve numbers, then `depth` could have simply been `Subtract<Options['depth'], 1>`
: never; // Should never happen
}> extends infer SubPath
? SubPath extends string | number
? (
Options['bracketNotation'] extends true
? SubPath extends `[${any}]` | `[${any}]${string}`
? `${TranformedKey}${SubPath}` // If next node is number key like `[3]`, no need to add `.` before it.
: `${TranformedKey}.${SubPath}`
: never
) | (
Options['bracketNotation'] extends false
? `${TranformedKey}.${SubPath}`
: never
)
: never
: never
: never
)
: never
: never
}[keyof T & (T extends UnknownArray ? number : unknown)]
: never
: never;
/**
* 判断 `T` 是否是 `any` 类型。
*
* @public
* @see https://stackoverflow.com/a/49928360
* @example
* ```typescript
* type X = IsAny<any>
* // => true
* ```
*/
export declare type IsAny<T> = 0 extends 1 & T ? true : false;
/**
Returns a boolean for whether the given type is `any`.
@link https://stackoverflow.com/a/49928360/1490091
Useful in type utilities, such as disallowing `any`s to be passed to a function.
@example
```
import type {IsAny} from 'type-fest';
const typedObject = {a: 1, b: 2} as const;
const anyObject: any = {a: 1, b: 2};
function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(obj: O, key: K) {
return obj[key];
}
const typedA = get(typedObject, 'a');
//=> 1
const anyA = get(anyObject, 'a');
//=> any
```
@category Type Guard
@category Utilities
*/
declare type IsAny_2<T> = 0 extends 1 & NoInfer_2<T> ? true : false;
/**
* 判断 `T` 是否是空数组。
*
* @public
* @example
* ```typescript
* type X = IsEmptyArray<[]>
* // => true
* ```
*/
export declare type IsEmptyArray<T> = T extends any[] ? T extends NonEmptyArray<any> ? false : true : false;
/**
* 判断 `T` 是否是空对象。
*
* @public
* @example
* ```typescript
* type X = IsEmptyObject<{}>
* // => true
* ```
*/
export declare type IsEmptyObject<T> = T extends Object ? IsNever<keyof T> : false;
/**
Returns a boolean for whether the two given types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
@link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
Use-cases:
- If you want to make a conditional branch based on the result of a comparison of two types.
@example
```
import type {IsEqual} from 'type-fest';
// This type returns a boolean for whether the given array includes the given item.
// `IsEqual` is used to compare the given array at position 0 and the given item and then return true if they are equal.
type Includes<Value extends readonly any[], Item> =
Value extends readonly [Value[0], ...infer rest]
? IsEqual<Value[0], Item> extends true
? true
: Includes<rest, Item>
: false;
```
@category Type Guard
@category Utilities
*/
declare type IsEqual<A, B> =
(<G>() => G extends A & G | G ? 1 : 2) extends
(<G>() => G extends B & G | G ? 1 : 2)
? true
: false;
declare type IsEqualConsideringWritability<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
? true
: false;
/**
Returns a boolean for whether the given number is a float, like `1.5` or `-1.5`.
It returns `false` for `Infinity`.
Use-case:
- If you want to make a conditional branch based on the result of whether a number is a float or not.
@example
```
type Float = IsFloat<1.5>;
//=> true
type IntegerWithDecimal = IsInteger<1.0>;
//=> false
type NegativeFloat = IsInteger<-1.5>;
//=> true
type Infinity_ = IsInteger<Infinity>;
//=> false
```
*/
declare type IsFloat<T> =
T extends number
? `${T}` extends `${infer _Sign extends '' | '-'}${number}.${infer Decimal extends number}`
? Decimal extends Zero
? false
: true
: false
: false;
declare type IsFullyWritable<T extends object> = IsEqualConsideringWritability<
{
[Q in keyof T]: T[Q];
},
Writable<
{
[Q in keyof T]: T[Q];
}
>
>;
/**
Returns a boolean for whether the given number is a integer, like `-5`, `1.0` or `100`.
Like [`Number#IsInteger()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/IsInteger) but for types.
Use-case:
- If you want to make a conditional branch based on the result of whether a number is a intrger or not.
@example
```
type Integer = IsInteger<1>;
//=> true
type IntegerWithDecimal = IsInteger<1.0>;
//=> true
type NegativeInteger = IsInteger<-1>;
//=> true
type Float = IsInteger<1.5>;
//=> false
// Supports non-decimal numbers
type OctalInteger: IsInteger<0o10>;
//=> true
type BinaryInteger: IsInteger<0b10>;
//=> true
type HexadecimalInteger: IsInteger<0x10>;
//=> true
```
*/
declare type IsInteger<T> =
T extends bigint
? true
: T extends number
? number extends T
? false
: T extends PositiveInfinity | NegativeInfinity
? false
: Not<IsFloat<T>>
: false;
/**
Returns a boolean for whether the given number is a negative number.
@see Negative
@example
```
import type {IsNegative} from 'type-fest';
type ShouldBeFalse = IsNegative<1>;
type ShouldBeTrue = IsNegative<-1>;
```
@category Numeric
*/
declare type IsNegative<T extends Numeric> = T extends Negative<T> ? true : false;
/**
* 判断 `T` 是否是 `never` 类型。
*
* @public
* @example
* ```typescript
* type X = IsNever<never>
* // => true
* ```
*/
export declare type IsNever<T> = [T] extends [never] ? true : false;
/**
Returns a boolean for whether the given type is `never`.
@link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
@link https://stackoverflow.com/a/53984913/10292952
@link https://www.zhenghao.io/posts/ts-never
Useful in type utilities, such as checking if something does not occur.
@example
```
import type {IsNever, And} from 'type-fest';
// https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
type AreStringsEqual<A extends string, B extends string> =
And<
IsNever<Exclude<A, B>> extends true ? true : false,
IsNever<Exclude<B, A>> extends true ? true : false
>;
type EndIfEqual<I extends string, O extends string> =
AreStringsEqual<I, O> extends true
? never
: void;
function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
if (input === output) {
process.exit(0);
}
}
endIfEqual('abc', 'abc');
//=> never
endIfEqual('abc', '123');
//=> void
```
@category Type Guard
@category Utilities
*/
declare type IsNever_2<T> = [T] extends [never] ? true : false;
/**
Returns a boolean for whether the given type is `null`.
@example
```
import type {IsNull} from 'type-fest';
type NonNullFallback<T, Fallback> = IsNull<T> extends true ? Fallback : T;
type Example1 = NonNullFallback<null, string>;
//=> string
type Example2 = NonNullFallback<number, string>;
//=? number
```
@category Type Guard
@category Utilities
*/
declare type IsNull<T> = [T] extends [null] ? true : false;
/**
Returns a boolean for whether the string is screaming snake case.
*/
declare type IsScreamingSnakeCase<Value extends string> = Value extends Uppercase<Value>
? Includes<SplitIncludingDelimiters<Lowercase<Value>, '_'>, '_'> extends true
? true
: false
: false;
declare type IsTuple<T> = T extends [infer A]
? T
: T extends [infer A, infer B]
? T
: T extends [infer A, infer B, infer C]
? T
: T extends [infer A, infer B, infer C, infer D]
? T
: T extends [infer A, infer B, infer C, infer D, infer E]
? T
: never;
/**
Returns a boolean for whether the given type is `unknown`.
@link https://github.com/dsherret/conditional-type-checks/pull/16
Useful in type utilities, such as when dealing with unknown data from API calls.
@example
```
import type {IsUnknown} from 'type-fest';
// https://github.com/pajecawav/tiny-global-store/blob/master/src/index.ts
type Action<TState, TPayload = void> =
IsUnknown<TPayload> extends true
? (state: TState) => TState,
: (state: TState, payload: TPayload) => TState;
class Store<TState> {
constructor(private state: TState) {}
execute<TPayload = void>(action: Action<TState, TPayload>, payload?: TPayload): TState {
this.state = action(this.state, payload);
return this.state;
}
// ... other methods
}
const store = new Store({value: 1});
declare const someExternalData: unknown;
store.execute(state => ({value: state.value + 1}));
//=> `TPayload` is `void`
store.execute((state, payload) => ({value: state.value + payload}), 5);
//=> `TPayload` is `5`
store.execute((state, payload) => ({value: state.value + payload}), someExternalData);
//=> Errors: `action` is `(state: TState) => TState`
```
@category Utilities
*/
declare type IsUnknown<T> = (
unknown extends T // `T` can be `unknown` or `any`
? IsNull<T> extends false // `any` can be `null`, but `unknown` can't be
? true
: false
: false
);
/**
Matches a JSON array.
@category JSON
*/
export declare type JsonArray = JsonValue[] | readonly JsonValue[];
/**
Matches a JSON object.
This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from. Don't use this as a direct return type as the user would have to double-cast it: `jsonObject as unknown as CustomResponse`. Instead, you could extend your CustomResponse type from it to ensure your type only uses JSON-compatible types: `interface CustomResponse extends JsonObject { … }`.
@category JSON
*/
export declare type JsonObject = {[Key in string]: JsonValue} & {[Key in string]?: JsonValue | undefined};
/**
Matches any valid JSON primitive value.
@category JSON
*/
declare type JsonPrimitive = string | number | boolean | null;
/**
Matches any valid JSON value.
@see `Jsonify` if you need to transform a type to one that is assignable to `JsonValue`.
@category JSON
*/
export declare type JsonValue = JsonPrimitive | JsonObject | JsonArray;
/**
Convert a string literal to kebab-case.
This can be useful when, for example, converting a camel-cased object property to a kebab-cased CSS class name or a command-line flag.
@example
```
import type {KebabCase} from 'type-fest';
// Simple
const someVariable: KebabCase<'fooBar'> = 'foo-bar';
// Advanced
type KebabCasedProperties<T> = {
[K in keyof T as KebabCase<K>]: T[K]
};
interface CliOptions {
dryRun: boolean;
includeFile: string;
foo: number;
}
const rawCliOptions: KebabCasedProperties<CliOptions> = {
'dry-run': true,
'include-file': 'bar.js',
foo: 123
};
```
@category Change case
@category Template literal
*/
export declare type KebabCase<Value> = DelimiterCase<Value, '-'>;
/**
Returns the last element of a union type.
@example
```
type Last = LastOfUnion<1 | 2 | 3>;
//=> 3
```
*/
declare type LastOfUnion<T> =
UnionToIntersection<T extends any ? () => T : never> extends () => (infer R)
? R
: never;
/**
Returns a boolean for whether a given number is less than another number.
@example
```
import type {LessThan} from 'type-fest';
LessThan<1, -5>;
//=> false
LessThan<1, 1>;
//=> false
LessThan<1, 5>;
//=> true
```
*/
declare type LessThan<A extends number, B extends number> = number extends A | B
? never
: GreaterThanOrEqual<A, B> extends true ? false : true;
/**
Allows creating a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union.
Currently, when a union type of a primitive type is combined with literal types, TypeScript loses all information about the combined literals. Thus, when such type is used in an IDE with autocompletion, no suggestions are made for the declared literals.
This type is a workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729). It will be removed as soon as it's not needed anymore.
@example
```
import type {LiteralUnion} from 'type-fest';
// Before
type Pet = 'dog' | 'cat' | string;
const pet: Pet = '';
// Start typing in your TypeScript-enabled IDE.
// You **will not** get auto-completion for `dog` and `cat` literals.
// After
type Pet2 = LiteralUnion<'dog' | 'cat', string>;
const pet: Pet2 = '';
// You **will** get auto-completion for `dog` and `cat` literals.
```
@category Type
*/
export declare type LiteralUnion<
LiteralType,
BaseType extends Primitive,
> = LiteralType | (BaseType & Record<never, never>);
/** Merge 2 types, properties types from the latter override the ones defined on the former type */
export declare type Merge<M, N> = Omit<M, keyof N> & N;
/**
A negative `number`/`bigint` (`-∞ < x < 0`)
Use-case: Validating and documenting parameters.
@see NegativeInteger
@see NonNegative
@category Numeric
*/
export declare type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never;
/**
Matches the hidden `-Infinity` type.
Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/32277) if you want to have this type as a built-in in TypeScript.
@see PositiveInfinity
@category Numeric
*/
// See https://github.com/microsoft/TypeScript/issues/31752
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
export declare type NegativeInfinity = -1e999;
/**
A negative (`-∞ < x < 0`) `number` that is an integer.
Equivalent to `Negative<Integer<T>>`.
You can't pass a `bigint` as they are already guaranteed to be integers, instead use `Negative<T>`.
Use-case: Validating and documenting parameters.
@see Negative
@see Integer
@category Numeric
*/
export declare type NegativeInteger<T extends number> = Negative<Integer<T>>;
declare type NoInfer_2<T> = T extends infer U ? U : never;
/**
* 非空数组类型。
*
* @public
* @example
* ```typescript
* type X = NonEmptyArray<number>
* const x: X = [] // => error
* ```
*/
export declare type NonEmptyArray<T> = [T, ...T[]];
/**
A non-negative `number`/`bigint` (`0 <= x < ∞`).
Use-case: Validating and documenting parameters.
@see NonNegativeInteger
@see Negative
@example
```
import type {NonNegative} from 'type-fest';
declare function setLength<T extends number>(length: NonNegative<T>): void;
```
@category Numeric
*/
export declare type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : never;
/**
A non-negative (`0 <= x < ∞`) `number` that is an integer.
Equivalent to `NonNegative<Integer<T>>`.
You can't pass a `bigint` as they are already guaranteed to be integers, instead use `NonNegative<T>`.
Use-case: Validating and documenting parameters.
@see NonNegative
@see Integer
@example
```
import type {NonNegativeInteger} from 'type-fest';
declare function setLength<T extends number>(length: NonNegativeInteger<T>): void;
```
@category Numeric
*/
export declare type NonNegativeInteger<T extends number> = NonNegative<Integer<T>>;
/** Like NonNullable but recursive */
export declare type NonNullableDeep<T> = T extends Builtin
? NonNullable<T>
: T extends Map<infer K, infer V>
? Map<NonNullableDeep<K>, NonNullableDeep<V>>
: T extends ReadonlyMap<infer K, infer V>
? ReadonlyMap<NonNullableDeep<K>, NonNullableDeep<V>>
: T extends WeakMap<infer K, infer V>
? WeakMap<NonNullableDeep<K>, NonNullableDeep<V>>
: T extends Set<infer U>
? Set<NonNullableDeep<U>>
: T extends ReadonlySet<infer U>
? ReadonlySet<NonNullableDeep<U>>
: T extends WeakSet<infer U>
? WeakSet<NonNullableDeep<U>>
: T extends Promise<infer U>
? Promise<NonNullableDeep<U>>
: T extends {}
? {
[K in keyof T]: NonNullableDeep<T[K]>;
}
: NonNullable<T>;
/**
Matches non-recursive types.
*/
declare type NonRecursiveType_2 = BuiltIns_2 | Function | (new (...arguments_: any[]) => unknown);
export declare type Nullable<T> = T | null | undefined;
/** Recursive nullable */
export declare type NullableDeep<T> = T extends Builtin
? T | null
: T extends Map<infer K, infer V>
? Map<NullableDeep<K>, NullableDeep<V>>
: T extends WeakMap<infer K, infer V>
? WeakMap<NullableDeep<K>, NullableDeep<V>>
: T extends Set<infer U>
? Set<NullableDeep<U>>
: T extends WeakSet<infer U>
? WeakSet<NullableDeep<U>>
: T extends Array<infer U>
? T extends IsTuple<T>
? {
[K in keyof T]: NullableDeep<T[K]> | null;
}
: Array<NullableDeep<U>>
: T extends Promise<infer U>
? Promise<NullableDeep<U>>
: T extends {}
? {
[K in keyof T]: NullableDeep<T[K]>;
}
: T | null;
declare type Numeric = number | bigint;
/** Omit all properties of given type in object type */
export declare type OmitBy<T, P> = Pick<
T,
{
[K in keyof T]: T[K] extends P ? never : K;
}[keyof T]
>;
/** Recursively omit deep properties */
export declare type OmitDeep<T extends DeepOmitModify<Filter>, Filter> = T extends Builtin
? T
: T extends Map<infer KeyType, infer ValueType>
? ValueType extends DeepOmitModify<Filter>
? Map<KeyType, OmitDeep<ValueType, Filter>>
: T
: T extends ReadonlyMap<infer KeyType, infer ValueType>
? ValueType extends DeepOmitModify<Filter>
? ReadonlyMap<KeyType, OmitDeep<ValueType, Filter>>
: T
: T extends WeakMap<infer KeyType, infer ValueType>
? ValueType extends DeepOmitModify<Filter>
? WeakMap<KeyType, OmitDeep<ValueType, Filter>>
: T
: T extends Set<infer ItemType>
? ItemType extends DeepOmitModify<Filter>
? Set<OmitDeep<ItemType, Filter>>
: T
: T extends ReadonlySet<infer ItemType>
? ItemType extends DeepOmitModify<Filter>
? ReadonlySet<OmitDeep<ItemType, Filter>>
: T
: T extends WeakSet<infer ItemType>
? ItemType extends DeepOmitModify<Filter>
? WeakSet<OmitDeep<ItemType, Filter>>
: T
: T extends Array<infer ItemType>
? ItemType extends DeepOmitModify<Filter>
? Array<OmitDeep<ItemType, Filter>>
: T
: T extends Promise<infer ItemType>
? ItemType extends DeepOmitModify<Filter>
? Promise<OmitDeep<ItemType, Filter>>
: T
: {
[K in Exclude<OptionalKeys<T>, keyof Filter>]+?: T[K];
} &
OmitBy<
{
[K in Extract<OptionalKeys<T>, keyof Filter>]+?: Filter[K] extends true
? never
: T[K] extends DeepOmitModify<Filter[K]>
? OmitDeep<T[K], Filter[K]>
: T[K];
},
never
> &
{
[K in Exclude<RequiredKeys<T>, keyof Filter>]: T[K];
} &
OmitBy<
{
[K in Extract<RequiredKeys<T>, keyof Filter>]: Filter[K] extends true
? never
: T[K] extends DeepOmitModify<Filter[K]>
? OmitDeep<T[K], Filter[K]>
: T[K];
},
never
>;
/** Similar to the builtin Omit, but checks the filter strictly. */
export declare type OmitStrict<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
/**
* 同 `T | T[]`。
*
* @public
* @example
* ```typescript
* type X = OneOrMore<number> // => number | number[]
* ```
*/
export declare type OneOrMore<T> = T | T[];
/** Gets keys of an object which are optional */
export declare type OptionalKeys<T> = {
[K in keyof T]-?: undefined extends {
[K2 in keyof T]: K2;
}[K]
? K
: never;
}[keyof T];
/**
Extract all optional keys from the given type.
This is useful when you want to create a new type that contains different type values for the optional keys only.
@example
```
import type {OptionalKeysOf, Except} from 'type-fest';
interface User {
name: string;
surname: string;
luckyNumber?: number;
}
const REMOVE_FIELD = Symbol('remove field symbol');
type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
[Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
};
const update1: UpdateOperation<User> = {
name: 'Alice'
};
const update2: UpdateOperation<User> = {
name: 'Bob',
luckyNumber: REMOVE_FIELD
};
```
@category Utilities
*/
declare type OptionalKeysOf<BaseType extends object> = Exclude<{
[Key in keyof BaseType]: BaseType extends Record<Key, BaseType[Key]>
? never
: Key
}[keyof BaseType], undefined>;
/**
Returns a boolean for whether either of two given types are true.
Use-case: Constructing complex conditional types where multiple conditions must be satisfied.
@example
```
import type {Or} from 'type-fest';
Or<true, false>;
//=> true
Or<false, false>;
//=> false
```
@see {@link And}
*/
declare type Or<A extends boolean, B extends boolean> = [A, B][number] extends false
? false
: true extends [IsEqual<A, true>, IsEqual<B, true>][number]
? true
: never;
export declare namespace PackageJson {
/**
A person who has been involved in creating or maintaining the package.
*/
export type Person =
| string
| {
name: string;
url?: string;
email?: string;
};
export type BugsLocation =
| string
| {
/**
The URL to the package's issue tracker.
*/
url?: string;
/**
The email address to which issues should be reported.
*/
email?: string;
};
export type DirectoryLocations = {
[directoryType: string]: JsonValue | undefined;
/**
Location for executable scripts. Sugar to generate entries in the `bin` property by walking the folder.
*/
bin?: string;
/**
Location for Markdown files.
*/
doc?: string;
/**
Location for example scripts.
*/
example?: string;
/**
Location for the bulk of the library.
*/
lib?: string;
/**
Location for man pages. Sugar to generate a `man` array by walking the folder.
*/
man?: string;
/**
Location for test files.
*/
test?: string;
};
export type Scripts = {
/**
Run **before** the package is published (Also run on local `npm install` without any arguments).
*/
prepublish?: string;
/**
Run both **before** the package is packed and published, and on local `npm install` without any arguments. This is run **after** `prepublish`, but **before** `prepublishOnly`.
*/
prepare?: string;
/**
Run **before** the package is prepared and packed, **only** on `npm publish`.
*/
prepublishOnly?: string;
/**
Run **before** a tarball is packed (on `npm pack`, `npm publish`, and when installing git dependencies).
*/
prepack?: string;
/**
Run **after** the tarball has been generated and moved to its final destination.
*/
postpack?: string;
/**
Run **after** the package is published.
*/
publish?: string;
/**
Run **after** the package is published.
*/
postpublish?: string;
/**
Run **before** the package is installed.
*/
preinstall?: string;
/**
Run **after** the package is installed.
*/
install?: string;
/**
Run **after** the package is installed and after `install`.
*/
postinstall?: string;
/**
Run **before** the package is uninstalled and before `uninstall`.
*/
preuninstall?: string;
/**
Run **before** the package is uninstalled.
*/
uninstall?: string;
/**
Run **after** the package is uninstalled.
*/
postuninstall?: string;
/**
Run **before** bump the package version and before `version`.
*/
preversion?: string;
/**
Run **before** bump the package version.
*/
version?: string;
/**
Run **after** bump the package version.
*/
postversion?: string;
/**
Run with the `npm test` command, before `test`.
*/
pretest?: string;
/**
Run with the `npm test` command.
*/
test?: string;
/**
Run with the `npm test` command, after `test`.
*/
posttest?: string;
/**
Run with the `npm stop` command, before `stop`.
*/
prestop?: string;
/**
Run with the `npm stop` command.
*/
stop?: string;
/**
Run with the `npm stop` command, after `stop`.
*/
poststop?: string;
/**
Run with the `npm start` command, before `start`.
*/
prestart?: string;
/**
Run with the `npm start` command.
*/
start?: string;
/**
Run with the `npm start` command, after `start`.
*/
poststart?: string;
/**
Run with the `npm restart` command, before `restart`. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided.
*/
prerestart?: string;
/**
Run with the `npm restart` command. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided.
*/
restart?: string;
/**
Run with the `npm restart` command, after `restart`. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided.
*/
postrestart?: string;
} & Partial<Record<string, string>>;
/**
Dependencies of the package. The version range is a string which has one or more space-separated descriptors. Dependencies can also be identified with a tarball or Git URL.
*/
export type Dependency = Partial<Record<string, string>>;
/**
A mapping of conditions and the paths to which they resolve.
*/
export type ExportConditions = { // eslint-disable-line @typescript-eslint/consistent-indexed-object-style
[condition: string]: Exports;
};
/**
Entry points of a module, optionally with conditions and subpath exports.
*/
export type Exports =
| null
| string
| Array<string | ExportConditions>
| ExportConditions;
/**
Import map entries of a module, optionally with conditions and subpath imports.
*/
export type Imports = { // eslint-disable-lin