diff --git a/src/array-types.ts b/src/array-types.ts index 4227b83..9482743 100644 --- a/src/array-types.ts +++ b/src/array-types.ts @@ -1,4 +1,3 @@ -import type { ToUnion } from "./object-types.js" import type { Equals } from "./test.js" /** @@ -229,18 +228,21 @@ export type AllEquals = Array extends [infe type ChunkImplementation< Array extends unknown[], - Size extends number, + Length extends number, Build extends unknown[] = [], Partition extends unknown[] = [], > = Array extends [infer Item, ...infer Spread] - ? [...Partition, Item]["length"] extends Size - ? ChunkImplementation - : ChunkImplementation - : Partition["length"] extends 0 + ? [...Partition, Item]["length"] extends Length + ? ChunkImplementation + : ChunkImplementation + : Size extends 0 ? Build : [...Build, Partition] -export type Chunk = ChunkImplementation +/** + * TODO: add examples + */ +export type Chunk = ChunkImplementation type ZipImplementation = T extends [infer ItemT, ...infer SpreadT] ? U extends [infer ItemU, ...infer SpreadU] @@ -290,25 +292,18 @@ export type CompareArrayLength = T extends [an ? U extends [any, ...infer SpreadU] ? CompareArrayLength : 1 - : U extends [infer Item, ...infer Spread] - ? -1 - : 0 + : Size extends 0 + ? 0 + : -1 type UniqueImplementation = Array extends [ infer Item, ...infer Spread, ] - ? HasImplementation extends true + ? Includes extends true ? UniqueImplementation : UniqueImplementation : Set - -type HasImplementation = Array extends [infer Item, ...infer Spread] - ? Equals extends true - ? true - : HasImplementation - : false - /** * Returns the uniques values of an array * @@ -320,3 +315,39 @@ type HasImplementation = Array * type Uniques2 = Unique<["a", "b", "c", "a", "b"]>; */ export type Unique = UniqueImplementation + +/** + * Create an union type based in the literal values of the tuple provided. + * This utility type is similar to `TupleToUnion` but this utility type + * receive whatever type + * + * @example + * // Expected: 1 + * type TupleNumber = ToUnion<1>; + * + * // Expected: "foo" + * type TupleString = ToUnion<"foo">; + * + * // Expected: 1 | ["foo" | "bar"] + * type TupleMultiple = ToUnion<1 | ["foo" | "bar"]>; + */ +export type ToUnion = T extends [infer Item, ...infer Spread] ? Item | ToUnion : T + +/** + * Check if a value exists within a tuple and is equal to a specific value + * + * @example + * // Expected: true + * type IncludesNumber = Includes<[1, 2, 3], 3>; + * + * // Expected: true + * type IncludesString = Includes<["foo", "bar", "foobar"], "bar">; + * + * // Expected: false + * type NoIncludes = Includes<["foo", "bar", "foofoo"], "foobar">; + */ +export type Includes = Array extends [infer Compare, ...infer Spread] + ? Equals extends true + ? true + : Includes + : false diff --git a/src/object-types.ts b/src/object-types.ts index 4932d29..c7d7b14 100644 --- a/src/object-types.ts +++ b/src/object-types.ts @@ -1,4 +1,5 @@ import type { Equals } from "./test.js" +import type { IsNever } from "./type-guards.js" import type { ArgsFunction, ReturnTypeOf } from "./types.js" /** @@ -35,11 +36,35 @@ export type DeepReadonly = { } /** + * TODO: add examples + * * Exclude properties of type `Match` from type `T` */ export type Exclude = T extends Match ? never : T /** + * Compare two types and return `never` if the type `T` extends the type `Match`, + * otherwise return the type `T`. + * + * @example + * // Expected: number + * type A = Discard; + * // Expected: string | number + * type B = Discard; + */ +export type Discard = Reverse extends true + ? Compare extends Match + ? Value + : never + : Compare extends Match + ? never + : IsNever extends true + ? Compare + : Value + +/** + * TODO: add examples + * * Get the type of the resolved value of a PromiseLike object. */ export type Awaited> = @@ -79,25 +104,6 @@ export type Pick = { [Property in Keys]: Obj[Property] } -/** - * Check if a value exists within a tuple and is equal to a specific value - * - * @example - * // Expected: true - * type IncludesNumber = Includes<[1, 2, 3], 3>; - * - * // Expected: true - * type IncludesString = Includes<["foo", "bar", "foobar"], "bar">; - * - * // Expected: false - * type NoIncludes = Includes<["foo", "bar", "foofoo"], "foobar">; - */ -export type Includes = Array extends [infer Compare, ...infer Spread] - ? Equals extends true - ? true - : Includes - : false - /** * Creates a new type that omits properties from an object type based on another type * @@ -106,7 +112,7 @@ export type Includes = Array extends [infer Comp * type NoEmailPerson = Omit<{ name: string; age: number; email: string }, "email">; */ export type Omit = { - [Property in keyof Obj as Property extends Keys ? never : Property]: Obj[Property] + [Property in keyof Obj as Discard]: Obj[Property] } /** @@ -124,7 +130,9 @@ export type Omit = { * // Expected: "foo" | "bar" * type PropsFooBar = Properties; */ -export type Properties = keyof Obj1 | keyof Obj2 +export type Properties = Extends extends true + ? keyof Obj1 & keyof Obj2 + : keyof Obj1 | keyof Obj2 /** * Creates a new object by merging two objects. Properties from `Obj1` override properties @@ -148,6 +156,10 @@ export type Merge = { [Property in Properties]: RetrieveKeyValue } +type IntersectionImplementation> = { + [Property in Properties as Discard]: RetrieveKeyValue +} + /** * Create a new object based in the difference keys between the objects. * @@ -166,13 +178,7 @@ export type Merge = { * // Expected: { gender: number } * type DiffFoo = Intersection; */ -export type Intersection = { - [Property in Properties as Property extends keyof Obj1 & keyof Obj2 ? never : Property]: RetrieveKeyValue< - Obj1, - Obj2, - Property - > -} +export type Intersection = IntersectionImplementation /** * Create a new object based in the type of its keys @@ -188,10 +194,12 @@ export type Intersection = { * type UserStr = PickByType; */ export type PickByType = { - [Property in keyof Obj as Obj[Property] extends Type ? Property : never]: Obj[Property] + [Property in keyof Obj as Discard]: Obj[Property] } /** + * TODO: add examples + * * Converts the specified keys of an object into optional ones * * @example @@ -205,9 +213,7 @@ export type PickByType = { * type UserPartialName = PartialByKeys; */ export type PartialByKeys = Prettify< - { - [Property in keyof Obj as Property extends Keys ? never : Property]: Obj[Property] - } & { [Property in Keys]?: Obj[Property] } + Partial> & Omit > /** @@ -228,23 +234,29 @@ export type OmitByType = { } /** + * TODO: add examples + * * Extracts the value of a key from an object and returns a new object with that value, * while keeping the other values unchanged. */ export type FlattenProperties = Prettify< { - [Property in keyof Obj as Property extends Keys ? never : Property]: Obj[Property] + [Property in keyof Obj as Discard]: Obj[Property] } & Obj[Keys] > /** + * TODO: add examples + * * Removes the properties whose keys start with an underscore (_). */ export type PublicOnly = { - [Property in keyof Obj as Property extends `_${string}` ? never : Property]: Obj[Property] + [Property in keyof Obj as Discard]: Obj[Property] } /** + * TODO: add examples + * * Checks if a key exists in either of the two objects and returns its value. * If the key does not exist in either object, it returns `never`. */ @@ -269,11 +281,7 @@ export type RetrieveKeyValue = Ke * type UserRequiredName = RequiredByKeys; */ export type RequiredByKeys = Prettify< - { - [Property in keyof Obj as Property extends Keys ? never : Property]: Obj[Property] - } & { - [Property in keyof Obj as Property extends Keys ? Property : never]-?: Obj[Property] - } + Required> & Omit > /** @@ -372,23 +380,6 @@ type MergeAllImplementation = MergeAllImplementation -/** - * Create an union type based in the literal values of the tuple provided. - * This utility type is similar to `TupleToUnion` but this utility type - * receive whatever type - * - * @example - * // Expected: 1 - * type TupleNumber = ToUnion<1>; - * - * // Expected: "foo" - * type TupleString = ToUnion<"foo">; - * - * // Expected: 1 | ["foo" | "bar"] - * type TupleMultiple = ToUnion<1 | ["foo" | "bar"]>; - */ -export type ToUnion = T extends [infer Item, ...infer Spread] ? Item | ToUnion : T - /** * Create a new object type appending a new property with its value * diff --git a/src/string-mappers.ts b/src/string-mappers.ts index d879ab2..f15acad 100644 --- a/src/string-mappers.ts +++ b/src/string-mappers.ts @@ -30,7 +30,8 @@ export type Trim = Str extends `${WhiteSpaces}${infer Charac : Str /** - * Converts a string to uppercase + * TODO: add example + * Converts a string to uppercase */ export type Uppercase = Str extends `${infer Char}${infer Characters}` ? Char extends keyof LetterToUppercase @@ -39,6 +40,7 @@ export type Uppercase = Str extends `${infer Char}${infer Ch : Str /** + * TODO: add example * Converts a string to lowercase */ export type Lowercase = Str extends `${infer Char}${infer Characters}` @@ -48,6 +50,7 @@ export type Lowercase = Str extends `${infer Char}${infer Ch : Str /** + * TODO: add example and fix the type * Capitalizes the first letter of a word and converts the rest to lowercase */ export type Capitalize = Str extends `${infer Char}${infer Characters}` diff --git a/test/array-types.test.ts b/test/array-types.test.ts index 8538315..48a7a73 100644 --- a/test/array-types.test.ts +++ b/test/array-types.test.ts @@ -164,3 +164,23 @@ describe("FlattenArrayType", () => { expectTypeOf>().toEqualTypeOf() }) }) + +describe("ToUnion", () => { + test("Create an union type", () => { + expectTypeOf>().toEqualTypeOf<12>() + expectTypeOf>().toEqualTypeOf<"foo">() + expectTypeOf>().toEqualTypeOf<12 | 21>() + expectTypeOf>().toEqualTypeOf<12 | 21 | "foo" | []>() + }) +}) + +describe("Includes", () => { + test("Check if an element exist withins a tuple", () => { + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + expectTypeOf void, {}], () => void>>().toEqualTypeOf() + expectTypeOf void, {}], string>>().toEqualTypeOf() + expectTypeOf void, {}], number>>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + }) +}) diff --git a/test/object-types.test.ts b/test/object-types.test.ts index 2323a7a..cf9eec0 100644 --- a/test/object-types.test.ts +++ b/test/object-types.test.ts @@ -168,15 +168,6 @@ describe("MergeAll", () => { }) }) -describe("ToUnion", () => { - test("Create an union type", () => { - expectTypeOf>().toEqualTypeOf<12>() - expectTypeOf>().toEqualTypeOf<"foo">() - expectTypeOf>().toEqualTypeOf<12 | 21>() - expectTypeOf>().toEqualTypeOf<12 | 21 | "foo" | []>() - }) -}) - describe("AddPropertyToObject", () => { test("Append a new property of an exist object type", () => { expectTypeOf>().toEqualTypeOf<{ @@ -252,17 +243,6 @@ describe("Parameters", () => { }) }) -describe("Includes", () => { - test("Check if an element exist withins a tuple", () => { - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - expectTypeOf void, {}], () => void>>().toEqualTypeOf() - expectTypeOf void, {}], string>>().toEqualTypeOf() - expectTypeOf void, {}], number>>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - }) -}) - describe("ObjectEntries", () => { test("Returns the entries from an object", () => { expectTypeOf>().toEqualTypeOf<["foo", string]>()