Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#34 - added usage document in JSDoc #68

Merged
merged 2 commits into from
Feb 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions src/mapped-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,42 @@
/**
* SetIntersection (same as Extract)
* @desc Set intersection of given union types `A` and `B`
* @example
* // Expect: "2" | "3"
* type ResultSet = SetIntersection<'1' | '2' | '3', '2' | '3' | '4'>;
*
* // Expect: () => void
rahgurung marked this conversation as resolved.
Show resolved Hide resolved
* type ResultSetMixed = SetIntersection<string | number | (() => void), Function>;
*/
export type SetIntersection<A, B> = A extends B ? A : never;

/**
* SetDifference (same as Exclude)
* @desc Set difference of given union types `A` and `B`
* @example
* // Expect: "1"
* type ResultSet = SetDifference<'1' | '2' | '3', '2' | '3' | '4'>;
*
* // Expect: string | number
* type ResultSetMixed = SetDifference<string | number | (() => void), Function>;
*/
export type SetDifference<A, B> = A extends B ? never : A;

/**
* SetComplement
* @desc Set complement of given union types `A` and (it's subset) `A1`
* @example
* // Expect: "1"
* type ResultSet = SetComplement<'1' | '2' | '3', '2' | '3'>;
*/
export type SetComplement<A, A1 extends A> = SetDifference<A, A1>;

/**
* SymmetricDifference
* @desc Set difference of union and intersection of given union types `A` and `B`
* @example
* // Expect: "1" | "4"
rahgurung marked this conversation as resolved.
Show resolved Hide resolved
* type ResultSet = SymmetricDifference<'1' | '2' | '3', '2' | '3' | '4'>;
*/
export type SymmetricDifference<A, B> = SetDifference<A | B, A & B>;

Expand All @@ -36,6 +54,11 @@ export type NonUndefined<A> = A extends undefined ? never : A;
/**
* FunctionKeys
* @desc get union type of keys that are functions in object type `T`
* @example
* type MixedProps = { name: string; setName: (name: string) => void };
rahgurung marked this conversation as resolved.
Show resolved Hide resolved
*
* // Expect: "setName"
* type FunctionKeysProps = FunctionKeys<MixedProps>;
*/
export type FunctionKeys<T extends object> = {
[K in keyof T]: T[K] extends Function ? K : never
Expand All @@ -44,6 +67,11 @@ export type FunctionKeys<T extends object> = {
/**
* NonFunctionKeys
* @desc get union type of keys that are non-functions in object type `T`
* @example
* type MixedProps = { name: string; setName: (name: string) => void };
*
* // Expect: "name"
* type NonFunctionKeysProps = NonFunctionKeys<MixedProps>;
*/
export type NonFunctionKeys<T extends object> = {
[K in keyof T]: T[K] extends Function ? never : K
Expand All @@ -52,6 +80,11 @@ export type NonFunctionKeys<T extends object> = {
/**
* Omit (complements Pick)
* @desc From `T` remove a set of properties `K`
* @example
* type Props = { name: string; age: number; visible: boolean };
*
* // Expect: { name: string; visible: boolean; }
* type RequiredProps = Omit<Props, 'age'>;
*/
export type Omit<T extends object, K extends keyof T> = T extends any
? Pick<T, SetDifference<keyof T, K>>
Expand All @@ -61,6 +94,11 @@ export type Omit<T extends object, K extends keyof T> = T extends any
* PickByValue
* @desc From `T` pick a set of properties with value type of `ValueType`.
* Credit: [Piotr Lewandowski](https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c)
* @example
* type Props = { name: string; age: number; visible: boolean };
*
* // Expect: { name: string; age: number }
* type RequiredProps = PickByValue<Props, string | number>;
*/
export type PickByValue<T, ValueType> = Pick<
T,
Expand All @@ -71,6 +109,11 @@ export type PickByValue<T, ValueType> = Pick<
* OmitByValue
* @desc From `T` remove a set of properties with value type of `ValueType`.
* Credit: [Piotr Lewandowski](https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c)
* @example
* type Props = { name: string; age: number; visible: boolean };
*
* // Expect: { visible: boolean }
* type RequiredProps = OmitByValue<Props, string | number>;
*/
export type OmitByValue<T, ValueType> = Pick<
T,
Expand All @@ -80,6 +123,12 @@ export type OmitByValue<T, ValueType> = 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 DuplicatedProps = Intersection<Props, DefaultProps>;
*/
export type Intersection<T extends object, U extends object> = T extends any
? Pick<T, SetIntersection<keyof T, keyof U>>
Expand All @@ -88,6 +137,12 @@ export type Intersection<T extends object, U extends object> = T extends any
/**
* 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 RequiredProps = Diff<Props, DefaultProps>;
*/
export type Diff<T extends object, U extends object> = Pick<
T,
Expand All @@ -97,6 +152,12 @@ export type Diff<T extends object, U extends object> = Pick<
/**
* Subtract
* @desc From `T` remove properties that exist in `T1` (`T1` is a subtype of `T`)
* @example
* type Props = { name: string; age: number; visible: boolean };
* type DefaultProps = { age: number };
*
* // Expect: { name: string; visible: boolean; }
* type RequiredProps = Subtract<Props, DefaultProps>;
*/
export type Subtract<T extends T1, T1 extends object> = Pick<
T,
Expand All @@ -106,6 +167,12 @@ export type Subtract<T extends T1, T1 extends object> = 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<Props, NewProps>;
*/
export type Overwrite<
T extends object,
Expand All @@ -116,6 +183,12 @@ export type Overwrite<
/**
* 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<Props, NewProps>;
*/
export type Assign<
T extends object,
Expand All @@ -132,6 +205,11 @@ export type Exact<A extends object> = 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<Props>;
*/
export type Unionize<T extends object> = {
[P in keyof T]: { [Q in P]: T[P] }
Expand All @@ -140,6 +218,9 @@ export type Unionize<T extends object> = {
/**
* PromiseType
* @desc Obtain Promise resolve type
* @example
* // Expect: string;
* type Response = PromiseType<Promise<string>>;
*/
export type PromiseType<T extends Promise<any>> = T extends Promise<infer U>
? U
Expand All @@ -149,6 +230,22 @@ export type PromiseType<T extends Promise<any>> = T extends Promise<infer U>
/**
* 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<NestedProps>;
*/
export type DeepReadonly<T> = T extends (...args: any[]) => any
? T
Expand All @@ -168,6 +265,22 @@ export type _DeepReadonlyObject<T> = {
/**
* DeepRequired
* @desc Required that works for deeply nested structure
* @example
* // Expect: {
* // first: {
* // second: {
* // name: string;
* // };
* // };
* // }
* type NestedProps = {
* first?: {
* second?: {
* name?: string;
* };
* };
* };
* type RequiredNestedProps = DeepRequired<NestedProps>;
*/
export type DeepRequired<T> = T extends (...args: any[]) => any
? T
Expand All @@ -188,6 +301,23 @@ export type _DeepRequiredObject<T> = {
/**
* 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<NestedProps>;
*/
export type DeepNonNullable<T> = T extends (...args: any[]) => any
? T
Expand All @@ -208,6 +338,22 @@ export type _DeepNonNullableObject<T> = {
/**
* DeepPartial
* @desc Partial that works for deeply nested structure
* @example
* // Expect: {
* // first?: {
* // second?: {
* // name?: string;
* // };
* // };
* // }
* type NestedProps = {
* first: {
* second: {
* name: string;
* };
* };
* };
* type PartialNestedProps = DeepPartial<NestedProps>;
*/
export type DeepPartial<T> =
T extends Function ? T :
Expand All @@ -231,6 +377,10 @@ type IfEquals<X, Y, A = X, B = never> =
* @desc get union type of keys that are writable in object type `T`
* Credit: Matt McCutchen
* https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript
* @example
* // Expect: "bar"
* type Props = { readonly foo: string; bar: number };
* type WritableProps = WritableKeys<Props>;
*/
export type WritableKeys<T extends object> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
Expand All @@ -241,6 +391,10 @@ export type WritableKeys<T extends object> = {
* @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
* // Expect: "foo"
* type Props = { readonly foo: string; bar: number };
* type ReadonlyProps = ReadonlyKeys<Props>;
*/
export type ReadonlyKeys<T extends object> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
Expand Down
Loading