import { Primitive } from './aliases-and-guards'; /** * Credits to all the people who given inspiration and shared some very useful code snippets * in the following github issue: https://github.com/Microsoft/TypeScript/issues/12215 */ /** * SetIntersection (same as Extract) * @desc Set intersection of given union types `A` and `B` * @example * // Expect: "2" | "3" * SetIntersection<'1' | '2' | '3', '2' | '3' | '4'>; * * // Expect: () => void * SetIntersection void), Function>; */ export declare type SetIntersection = A extends B ? A : never; /** * SetDifference (same as Exclude) * @desc Set difference of given union types `A` and `B` * @example * // Expect: "1" * SetDifference<'1' | '2' | '3', '2' | '3' | '4'>; * * // Expect: string | number * SetDifference void), Function>; */ export declare type SetDifference = A extends B ? never : A; /** * SetComplement * @desc Set complement of given union types `A` and (it's subset) `A1` * @example * // Expect: "1" * SetComplement<'1' | '2' | '3', '2' | '3'>; */ export declare type SetComplement = SetDifference; /** * SymmetricDifference * @desc Set difference of union and intersection of given union types `A` and `B` * @example * // Expect: "1" | "4" * SymmetricDifference<'1' | '2' | '3', '2' | '3' | '4'>; */ export declare type SymmetricDifference = SetDifference; /** * NonUndefined * @desc Exclude undefined from set `A` * @example * // Expect: "string | null" * SymmetricDifference; */ export declare type NonUndefined = A extends undefined ? never : A; /** * NonNullable * @desc Exclude undefined and null from set `A` * @example * // Expect: "string" * SymmetricDifference; */ /** * FunctionKeys * @desc Get union type of keys that are functions in object type `T` * @example * type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;}; * * // Expect: "setName | someFn" * type Keys = FunctionKeys; */ export declare type FunctionKeys = { [K in keyof T]-?: NonUndefined extends Function ? K : never; }[keyof T]; /** * NonFunctionKeys * @desc Get union type of keys that are non-functions in object type `T` * @example * type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;}; * * // Expect: "name | someKey" * type Keys = NonFunctionKeys; */ export declare type NonFunctionKeys = { [K in keyof T]-?: NonUndefined extends Function ? never : K; }[keyof T]; /** * MutableKeys * @desc Get union type of keys that are mutable in object type `T` * Credit: Matt McCutchen * https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript * @example * type Props = { readonly foo: string; bar: number }; * * // Expect: "bar" * type Keys = MutableKeys; */ export declare type MutableKeys = { [P in keyof T]-?: IfEquals<{ [Q in P]: T[P]; }, { -readonly [Q in P]: T[P]; }, P>; }[keyof T]; export declare type WritableKeys = MutableKeys; /** * ReadonlyKeys * @desc Get union type of keys that are readonly in object type `T` * Credit: Matt McCutchen * https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript * @example * type Props = { readonly foo: string; bar: number }; * * // Expect: "foo" * type Keys = ReadonlyKeys; */ export declare type ReadonlyKeys = { [P in keyof T]-?: IfEquals<{ [Q in P]: T[P]; }, { -readonly [Q in P]: T[P]; }, never, P>; }[keyof T]; declare type IfEquals = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? A : B; /** * RequiredKeys * @desc Get union type of keys that are required in object type `T` * @see https://stackoverflow.com/questions/52984808/is-there-a-way-to-get-all-required-properties-of-a-typescript-object * @example * type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; }; * * // Expect: "req" | "reqUndef" * type Keys = RequiredKeys; */ export declare type RequiredKeys = { [K in keyof T]-?: {} extends Pick ? never : K; }[keyof T]; /** * OptionalKeys * @desc Get union type of keys that are optional in object type `T` * @see https://stackoverflow.com/questions/52984808/is-there-a-way-to-get-all-required-properties-of-a-typescript-object * @example * type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; }; * * // Expect: "opt" | "optUndef" * type Keys = OptionalKeys; */ export declare type OptionalKeys = { [K in keyof T]-?: {} extends Pick ? K : never; }[keyof T]; /** * PickByValue * @desc From `T` pick a set of properties by value matching `ValueType`. * Credit: [Piotr Lewandowski](https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c) * @example * type Props = { req: number; reqUndef: number | undefined; opt?: string; }; * * // Expect: { req: number } * type Props = PickByValue; * // Expect: { req: number; reqUndef: number | undefined; } * type Props = PickByValue; */ export declare type PickByValue = Pick; /** * PickByValueExact * @desc From `T` pick a set of properties by value matching exact `ValueType`. * @example * type Props = { req: number; reqUndef: number | undefined; opt?: string; }; * * // Expect: { req: number } * type Props = PickByValueExact; * // Expect: { reqUndef: number | undefined; } * type Props = PickByValueExact; */ export declare type PickByValueExact = Pick; /** * Omit (complements Pick) * @desc From `T` remove a set of properties by key `K` * @example * type Props = { name: string; age: number; visible: boolean }; * * // Expect: { name: string; visible: boolean; } * type Props = Omit; */ export declare type Omit = Pick>; /** * OmitByValue * @desc From `T` remove a set of properties by value matching `ValueType`. * Credit: [Piotr Lewandowski](https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c) * @example * type Props = { req: number; reqUndef: number | undefined; opt?: string; }; * * // Expect: { reqUndef: number | undefined; opt?: string; } * type Props = OmitByValue; * // Expect: { opt?: string; } * type Props = OmitByValue; */ export declare type OmitByValue = Pick; /** * OmitByValueExact * @desc From `T` remove a set of properties by value matching exact `ValueType`. * @example * type Props = { req: number; reqUndef: number | undefined; opt?: string; }; * * // Expect: { reqUndef: number | undefined; opt?: string; } * type Props = OmitByValueExact; * // Expect: { req: number; opt?: string } * type Props = OmitByValueExact; */ export declare type OmitByValueExact = Pick; /** * Intersection * @desc From `T` pick properties that exist in `U` * @example * type Props = { name: string; age: number; visible: boolean }; * type DefaultProps = { age: number }; * * // Expect: { age: number; } * type DuplicateProps = Intersection; */ export declare type Intersection = Pick & Extract>; /** * Diff * @desc From `T` remove properties that exist in `U` * @example * type Props = { name: string; age: number; visible: boolean }; * type DefaultProps = { age: number }; * * // Expect: { name: string; visible: boolean; } * type DiffProps = Diff; */ export declare type Diff = Pick>; /** * Subtract * @desc From `T` remove properties that exist in `T1` (`T1` has a subset of the properties of `T`) * @example * type Props = { name: string; age: number; visible: boolean }; * type DefaultProps = { age: number }; * * // Expect: { name: string; visible: boolean; } * type RestProps = Subtract; */ export declare type Subtract = Pick>; /** * Overwrite * @desc From `U` overwrite properties to `T` * @example * type Props = { name: string; age: number; visible: boolean }; * type NewProps = { age: string; other: string }; * * // Expect: { name: string; age: string; visible: boolean; } * type ReplacedProps = Overwrite; */ export declare type Overwrite & Intersection> = Pick; /** * Assign * @desc From `U` assign properties to `T` (just like object assign) * @example * type Props = { name: string; age: number; visible: boolean }; * type NewProps = { age: string; other: string }; * * // Expect: { name: string; age: number; visible: boolean; other: string; } * type ExtendedProps = Assign; */ export declare type Assign & Intersection & Diff> = Pick; /** * Exact * @desc Create branded object type for exact type matching */ export declare type Exact = A & { __brand: keyof A; }; /** * Unionize * @desc Disjoin object to form union of objects, each with single property * @example * type Props = { name: string; age: number; visible: boolean }; * * // Expect: { name: string; } | { age: number; } | { visible: boolean; } * type UnionizedType = Unionize; */ export declare type Unionize = { [P in keyof T]: { [Q in P]: T[P]; }; }[keyof T]; /** * PromiseType * @desc Obtain Promise resolve type * @example * // Expect: string; * type Response = PromiseType>; */ export declare type PromiseType> = T extends Promise ? U : never; /** * DeepReadonly * @desc Readonly that works for deeply nested structure * @example * // Expect: { * // readonly first: { * // readonly second: { * // readonly name: string; * // }; * // }; * // } * type NestedProps = { * first: { * second: { * name: string; * }; * }; * }; * type ReadonlyNestedProps = DeepReadonly; */ export declare type DeepReadonly = T extends ((...args: any[]) => any) | Primitive ? T : T extends _DeepReadonlyArray ? _DeepReadonlyArray : T extends _DeepReadonlyObject ? _DeepReadonlyObject : T; /** @private */ export interface _DeepReadonlyArray extends ReadonlyArray> { } /** @private */ export declare type _DeepReadonlyObject = { readonly [P in keyof T]: DeepReadonly; }; /** * DeepRequired * @desc Required that works for deeply nested structure * @example * // Expect: { * // first: { * // second: { * // name: string; * // }; * // }; * // } * type NestedProps = { * first?: { * second?: { * name?: string; * }; * }; * }; * type RequiredNestedProps = DeepRequired; */ export declare type DeepRequired = T extends (...args: any[]) => any ? T : T extends any[] ? _DeepRequiredArray : T extends object ? _DeepRequiredObject : T; /** @private */ export interface _DeepRequiredArray extends Array>> { } /** @private */ export declare type _DeepRequiredObject = { [P in keyof T]-?: DeepRequired>; }; /** * DeepNonNullable * @desc NonNullable that works for deeply nested structure * @example * // Expect: { * // first: { * // second: { * // name: string; * // }; * // }; * // } * type NestedProps = { * first?: null | { * second?: null | { * name?: string | null | * undefined; * }; * }; * }; * type RequiredNestedProps = DeepNonNullable; */ export declare type DeepNonNullable = T extends (...args: any[]) => any ? T : T extends any[] ? _DeepNonNullableArray : T extends object ? _DeepNonNullableObject : T; /** @private */ export interface _DeepNonNullableArray extends Array>> { } /** @private */ export declare type _DeepNonNullableObject = { [P in keyof T]-?: DeepNonNullable>; }; /** * DeepPartial * @desc Partial that works for deeply nested structure * @example * // Expect: { * // first?: { * // second?: { * // name?: string; * // }; * // }; * // } * type NestedProps = { * first: { * second: { * name: string; * }; * }; * }; * type PartialNestedProps = DeepPartial; */ export declare type DeepPartial = { [P in keyof T]?: _DeepPartial; }; /** @private */ export declare type _DeepPartial = T extends Function ? T : T extends Array ? _DeepPartialArray : T extends object ? DeepPartial : T | undefined; /** @private */ export interface _DeepPartialArray extends Array<_DeepPartial> { } /** * Brand * @desc Define nominal type of U based on type of T. Similar to Opaque types in Flow. * @example * type USD = Brand * type EUR = Brand * * const tax = 5 as USD; * const usd = 10 as USD; * const eur = 10 as EUR; * * function gross(net: USD): USD { * return (net + tax) as USD; * } * * // Expect: No compile error * gross(usd); * // Expect: Compile error (Type '"EUR"' is not assignable to type '"USD"'.) * gross(eur); */ export declare type Brand = T & { __brand: U; }; /** * Optional * @desc From `T` make a set of properties by key `K` become optional * @example * type Props = { * name: string; * age: number; * visible: boolean; * }; * * // Expect: { name?: string; age?: number; visible?: boolean; } * type Props = Optional; * * // Expect: { name: string; age?: number; visible?: boolean; } * type Props = Optional; */ export declare type Optional = Omit & Partial>; /** * ValuesType * @desc Get the union type of all the values in an object, array or array-like type `T` * @example * type Props = { name: string; age: number; visible: boolean }; * // Expect: string | number | boolean * type PropsValues = ValuesType; * * type NumberArray = number[]; * // Expect: number * type NumberItems = ValuesType; * * type ReadonlySymbolArray = readonly symbol[]; * // Expect: symbol * type SymbolItems = ValuesType; * * type NumberTuple = [1, 2]; * // Expect: 1 | 2 * type NumberUnion = ValuesType; * * type ReadonlyNumberTuple = readonly [1, 2]; * // Expect: 1 | 2 * type AnotherNumberUnion = ValuesType; * * type BinaryArray = Uint8Array; * // Expect: number * type BinaryItems = ValuesType; */ export declare type ValuesType | ArrayLike | Record> = T extends ReadonlyArray ? T[number] : T extends ArrayLike ? T[number] : T extends object ? T[keyof T] : never; /** * Required * @desc From `T` make a set of properties by key `K` become required * @example * type Props = { * name?: string; * age?: number; * visible?: boolean; * }; * * // Expect: { name: string; age: number; visible: boolean; } * type Props = Required; * * // Expect: { name?: string; age: number; visible: boolean; } * type Props = Required; */ export declare type AugmentedRequired = Omit & Required>; /** * UnionToIntersection * @desc Get intersection type given union type `U` * Credit: jcalz * @see https://stackoverflow.com/a/50375286/7381355 * @example * // Expect: { name: string } & { age: number } & { visible: boolean } * UnionToIntersection<{ name: string } | { age: number } | { visible: boolean }> */ export declare type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; /** * Mutable * @desc From `T` make all properties become mutable * @example * type Props = { * readonly name: string; * readonly age: number; * readonly visible: boolean; * }; * * // Expect: { name: string; age: number; visible: boolean; } * Mutable; */ export declare type Mutable = { -readonly [P in keyof T]: T[P]; }; export declare type Writable = Mutable; export {};