diff --git a/README.md b/README.md index 48b1aaa..dab4e3e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ npm install --save-dev simplytyped **[Objects](#objects)** -[AllKeys](#allkeys) - [AllRequired](#allrequired) - [CombineObjects](#combineobjects) - [DeepPartial](#deeppartial) - [DeepReadonly](#deepreadonly) - [DiffKeys](#diffkeys) - [GetKey](#getkey) - [HasKey](#haskey) - [Intersect](#intersect) - [Keys](#keys) - [KeysByType](#keysbytype) - [Merge](#merge) - [ObjectKeys](#objectkeys) - [ObjectType](#objecttype) - [Omit](#omit) - [Optional](#optional) - [Overwrite](#overwrite) - [PlainObject](#plainobject) - [PureKeys](#purekeys) - [Required](#required) - [SharedKeys](#sharedkeys) - [StrictUnion](#strictunion) - [StringKeys](#stringkeys) - [TaggedObject](#taggedobject) - [UnionizeProperties](#unionizeproperties) - [UnionKeys](#unionkeys) +[AllKeys](#allkeys) - [AllRequired](#allrequired) - [CombineObjects](#combineobjects) - [DeepPartial](#deeppartial) - [DeepReadonly](#deepreadonly) - [DiffKeys](#diffkeys) - [GetKey](#getkey) - [HasKey](#haskey) - [Intersect](#intersect) - [KeysByType](#keysbytype) - [Merge](#merge) - [ObjectKeys](#objectkeys) - [ObjectType](#objecttype) - [Omit](#omit) - [Optional](#optional) - [Overwrite](#overwrite) - [PlainObject](#plainobject) - [PureKeys](#purekeys) - [Required](#required) - [SharedKeys](#sharedkeys) - [StrictUnion](#strictunion) - [StringKeys](#stringkeys) - [TaggedObject](#taggedobject) - [UnionizeProperties](#unionizeproperties) - [UnionKeys](#unionkeys) **[Utils](#utils)** @@ -221,7 +221,7 @@ test('Can make an object with functions readonly', t => { ### DiffKeys Gets all of the keys that are different between two objects. -This is a set difference between `Keys` and `Keys`. +This is a set difference between `keyof T` and `keyof U`. Note that calling this with arguments reversed will have different results. ```ts test('Can get all keys that are different between objects', t => { @@ -283,20 +283,6 @@ test('Can get an object with only shared properties', t => { ``` -### Keys -No different than `keyof`, but can look a bit nicer when nesting many types deep. -```ts -test('Can get keys from object', t => { - type obj = { x: number, y: string, z: boolean }; - type expected = 'x' | 'y' | 'z'; - type got = Keys; - - assert(t); - assert(t); -}); - -``` - ### KeysByType Gets all keys that point to a given type. ```ts diff --git a/src/impl/objects.ts b/src/impl/objects.ts index 4391cfe..5604dd5 100644 --- a/src/impl/objects.ts +++ b/src/impl/objects.ts @@ -1,4 +1,4 @@ -import { DeepReadonly, Keys, TaggedObject, ObjectKeys } from '../types/objects'; +import { DeepReadonly, TaggedObject } from '../types/objects'; /** * Type guard for any key, `k`. @@ -6,7 +6,7 @@ import { DeepReadonly, Keys, TaggedObject, ObjectKeys } from '../types/objects'; * @param obj object to query for key `k` * @param k key to check existence in `obj` */ -export function isKeyOf(obj: T, k: ObjectKeys): k is keyof T { +export function isKeyOf(obj: T, k: keyof any): k is keyof T { return k in obj; } @@ -17,7 +17,7 @@ export function isKeyOf(obj: T, k: ObjectKeys): k is keyof T { * @returns an array of keys from `obj` */ export function objectKeys(obj: T) { - return Object.keys(obj) as Array>; + return Object.keys(obj) as Array; } /** @@ -34,7 +34,7 @@ export function Readonly(obj: T): DeepReadonly { return obj * @param key the name of the "tag" parameter * @returns `obj` with the inner objects tagged with parameter `key` and the key pointing to that inner object */ -export function taggedObject, K extends string>(obj: T, key: K): TaggedObject { +export function taggedObject, K extends string>(obj: T, key: K): TaggedObject { const keys = objectKeys(obj); return keys.reduce((collection: any, k) => { const inner: any = obj[k]; diff --git a/src/types/functions.ts b/src/types/functions.ts index 168493a..60a7462 100644 --- a/src/types/functions.ts +++ b/src/types/functions.ts @@ -21,7 +21,7 @@ export type AnyFunc = (...args: any[]) => R; * @param R the new return value of the function * @returns the function `F` with new return value `R` */ -export type OverwriteReturn = +export type OverwriteReturn = F extends ((...x: infer T) => unknown) ? ((...x: T) => R) : never; /** @@ -29,5 +29,5 @@ export type OverwriteReturn = * @param F a function with up to 7 arguments * @returns a tuple containing `F`'s argument types */ -export type ArgsAsTuple = +export type ArgsAsTuple = F extends ((...x: infer T) => unknown) ? T : never; diff --git a/src/types/objects.ts b/src/types/objects.ts index 3b48b80..b86ba4b 100644 --- a/src/types/objects.ts +++ b/src/types/objects.ts @@ -1,5 +1,4 @@ import { False, True } from './conditionals'; -import { AnyFunc } from './functions'; // ------- // Helpers @@ -15,7 +14,7 @@ export type PlainObject = Record; * @returns An object formed by the key, value pairs of T */ export type ObjectType = { - [k in Keys]: T[k]; + [k in keyof T]: T[k]; }; /** * Takes two objects and returns their intersection. @@ -34,7 +33,7 @@ export type CombineObjects = ObjectType = K extends Keys ? T[K] : never; +export type GetKey = K extends keyof T ? T[K] : never; // ---- // Keys @@ -55,13 +54,7 @@ export type ObjectKeys = keyof any; * @param T type from which to get keys * @returns keys of `T` that extend `string` */ -export type StringKeys = Exclude, number | symbol>; -/** - * No different than `keyof`, but can look a bit nicer when nesting many types deep. - * @param T type from which to get keys - * @returns keys of `T` that extend `string | number | symbol` - */ -export type Keys = keyof T; +export type StringKeys = Exclude; /** * When an object has optional or readonly keys, that information is contained within the key. * When using optional/readonly keys in another object, they will retain optional/readonly status. @@ -69,37 +62,37 @@ export type Keys = keyof T; * @param T type from which to get keys * @returns keys of `T` without status modifiers (readonly/optional) */ -export type PureKeys = Record, Keys>[Keys]; +export type PureKeys = Record[keyof T]; /** * Gets all of the keys that are shared between two objects. * @param T first type from which keys will be pulled * @param U second type from which keys will be pulled * @returns the keys that both `T` and `U` have in common. */ -export type SharedKeys = Keys & Keys; +export type SharedKeys = keyof T & keyof U; /** * Gets all keys between two objects. * @param T first type from which keys will be pulled * @param U second type from which keys will be pulled * @returns the keys of `T` in addition to the keys of `U` */ -export type AllKeys = Keys | Keys; +export type AllKeys = keyof T | keyof U; /** * Gets all of the keys that are different between two objects. - * This is a set difference between `Keys` and `Keys`. + * This is a set difference between `keyof T` and `keyof U`. * Note that calling this with arguments reversed will have different results. * @param T first type from which keys will be pulled * @param U second type from which keys will be pulled * @returns keys of `T` minus the keys of `U` */ -export type DiffKeys = Exclude, Keys>; +export type DiffKeys = Exclude; /** * Returns `True` if a key, `K`, is present in a type, `T`, else `False`. * @param T type to check for existence of key `K`. * @param K key to query `T` for * @returns `True` if `K` is a key of `T`. Else `False`. */ -export type HasKey = K extends Keys ? True : False; +export type HasKey = K extends keyof T ? True : False; /** * @param T the union to get the keys of @@ -118,7 +111,7 @@ export type UnionKeys * @param T the object whose property values will be unionized * @returns a union of the right-side values of `T` */ -export type UnionizeProperties = T[Keys]; +export type UnionizeProperties = T[keyof T]; /** * Gives back an object with listed keys removed. * This is the opposite of `Pick`. @@ -126,7 +119,7 @@ export type UnionizeProperties = T[Keys]; * @param K the union of keys to remove from `T` * @returns `T` with the keys `K` removed */ -export type Omit> = Pick, K>>; +export type Omit = Pick>; /** * Returns only the shared properties between two objects. * All shared properties must be the same type. @@ -159,8 +152,8 @@ export type Merge = Overwrite & U; * @param Key the key to add to each inner object as the tag property * @returns a record where each key of the record is now the `Key` property of the inner object */ -export type TaggedObject, Key extends ObjectKeys> = { - [K in Keys]: T[K] & Record; +export type TaggedObject, Key extends keyof any> = { + [K in keyof T]: T[K] & Record; }; // --------- @@ -175,7 +168,7 @@ export type TaggedObject, Key extends Objec export type DeepPartial = Partial<{ [k in keyof T]: T[k] extends unknown[] ? Array> : - T[k] extends AnyFunc ? T[k] : + T[k] extends Function ? T[k] : T[k] extends object ? DeepPartial : T[k]; }>; @@ -185,7 +178,7 @@ export type DeepPartial = Partial<{ * @returns `T` with all fields marked required */ export type AllRequired = { - [K in Keys]-?: NonNullable + [K in keyof T]-?: NonNullable }; /** * Mark specific keys, `K`, of `T` as required. @@ -193,7 +186,7 @@ export type AllRequired = { * @param K keys of `T` that will be marked required * @returns `T` with keys, `K`, marked as required */ -export type Required> = CombineObjects< +export type Required = CombineObjects< {[k in K]-?: NonNullable }, Omit >; @@ -203,7 +196,7 @@ export type Required> = CombineObjects< * @param K keys of `T` that will be marked optional * @returns `T` with keys, `K`, marked as optional */ -export type Optional> = CombineObjects< +export type Optional = CombineObjects< {[k in K]?: T[k] | undefined }, Omit >; @@ -215,7 +208,7 @@ export type Optional> = CombineObjects< export type DeepReadonly = Readonly<{ [k in keyof T]: T[k] extends unknown[] ? ReadonlyArray> : - T[k] extends AnyFunc ? T[k] : + T[k] extends Function ? T[k] : T[k] extends object ? DeepReadonly : T[k]; }>; diff --git a/src/types/predicates.ts b/src/types/predicates.ts index 0a9e871..0941e88 100644 --- a/src/types/predicates.ts +++ b/src/types/predicates.ts @@ -1,21 +1,19 @@ import { False, True, And, Or, Not } from './conditionals'; -import { Keys } from './objects'; -import { AnyFunc } from './functions'; /** no-doc */ export type KnownProblemPrototypeKeys = 'toString' | 'toLocaleString' | 'hasOwnProperty' | 'isPrototypeOf' | 'propertyIsEnumerable' | 'constructor' | 'valueOf'; /** no-doc */ export type ArrayPrototypeKeys = keyof unknown[]; /** no-doc */ -export type NumberPrototypeKeys = Keys; +export type NumberPrototypeKeys = keyof number; /** no-doc */ -export type BooleanPrototypeKeys = Keys; +export type BooleanPrototypeKeys = keyof false; /** no-doc */ -export type StringPrototypeKeys = Keys; +export type StringPrototypeKeys = keyof string; /** no-doc */ -export type ObjectPrototypeKeys = Keys; // tslint:disable-line +export type ObjectPrototypeKeys = keyof Object; /** no-doc */ -export type FunctionPrototypeKeys = Keys; // tslint:disable-line +export type FunctionPrototypeKeys = keyof Function; export type IsNever = Not<(Record & Record)[S]>; export type IsType = X extends T ? True : False; @@ -24,8 +22,8 @@ export type IsNumber = T extends number ? True : False; export type IsString = T extends string ? True : False; export type IsFunction = Or< - T extends AnyFunc ? True : False, - T extends Function ? True : False>; // tslint:disable-line + T extends Function ? True : False, + T extends Function ? True : False>; export type IsStringFunction = And, IsNever>; export type IsBoolean = T extends boolean ? True : False; diff --git a/test/objects/Keys.test.ts b/test/objects/Keys.test.ts deleted file mode 100644 index 43897c3..0000000 --- a/test/objects/Keys.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import test from 'ava'; -import { assert } from '../helpers/assert'; - -import { Keys } from '../../src'; - -test('Can get keys from object', t => { - type obj = { x: number, y: string, z: boolean }; - type expected = 'x' | 'y' | 'z'; - type got = Keys; - - assert(t); - assert(t); -}); diff --git a/test/prototypes.test.ts b/test/prototypes.test.ts index 04a5379..68da955 100644 --- a/test/prototypes.test.ts +++ b/test/prototypes.test.ts @@ -68,7 +68,7 @@ test('Can check if a type is a string', t => { test('Can check if a type is a function', t => { assert, True>(t); - assert, True>(t); // tslint:disable-line + assert, True>(t); assert, False>(t); assert, False>(t); diff --git a/tslint.json b/tslint.json index bbbe297..71850df 100644 --- a/tslint.json +++ b/tslint.json @@ -5,6 +5,7 @@ ], "rules": { "arrow-parens": false, + "ban-types": false, "curly": false, "indent": [ true,