Skip to content

Commit

Permalink
#34 - added usage document in JSDoc (#68)
Browse files Browse the repository at this point in the history
* #34 - added usage document in JSDoc

* added spacing and corrected expected comments
  • Loading branch information
rahgurung authored and piotrwitek committed Feb 23, 2019
1 parent eb78a15 commit 2270530
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
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
* 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"
* 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 };
*
* // 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

0 comments on commit 2270530

Please sign in to comment.