From d19ddb855dea08105a3d7450a98696c7bcd62f60 Mon Sep 17 00:00:00 2001 From: idchlife Date: Tue, 2 Jan 2018 22:27:59 +0300 Subject: [PATCH] Types for check-types (#22554) * Types for check-types * added version * added tsconfig.json * fixes for tslint * tests, some improv * missing semicolon fix * added tests file to tsconfig * fixed errors * removed redundant comment * updated tests and types with info from creator of lib --- types/check-types/check-types-tests.ts | 57 +++++++++ types/check-types/index.d.ts | 162 +++++++++++++++++++++++++ types/check-types/tsconfig.json | 21 ++++ types/check-types/tslint.json | 1 + 4 files changed, 241 insertions(+) create mode 100644 types/check-types/check-types-tests.ts create mode 100644 types/check-types/index.d.ts create mode 100644 types/check-types/tsconfig.json create mode 100644 types/check-types/tslint.json diff --git a/types/check-types/check-types-tests.ts b/types/check-types/check-types-tests.ts new file mode 100644 index 0000000000..1f0fc31c98 --- /dev/null +++ b/types/check-types/check-types-tests.ts @@ -0,0 +1,57 @@ +import * as check from "check-types"; + +const a: boolean = check.number(2); + +const b: any = 2; + +if (check.string(b)) { + const c = b.slice(0, 1); +} + +check.map({ val: 1, val2: 2 }, { val: check.number, val2: check.string }); + +check.even(3); + +check.not.even(3); + +check.maybe.even(2); + +check.assert.like({ foo: 'bar' }, { baz: 'qux' }); + +check.assert(false, "msg", Error); + +check.assert.not.like({ foo: 'bar' }, { baz: 'qux' }); + +check.assert.maybe.like(undefined, { foo: 'bar' }); + +check.assert(function a(): any { return {}; }, 'Something went wrong', Error); + +check.apply([ 'foo', 'bar', '' ], check.nonEmptyString); + +check.any( + check.apply( + [ 1, 2, 3, '' ], + check.string + ) +); + +check.any( + check.map( + { foo: 0, bar: '' }, + { foo: check.number, bar: check.string } + ) +); + +check.all( + check.map( + { foo: 0, bar: '' }, + { foo: check.number, bar: check.string } + ) +); + +check.all( + check.apply( + [ 1, 2, 3, '' ], + check.string + ) +); diff --git a/types/check-types/index.d.ts b/types/check-types/index.d.ts new file mode 100644 index 0000000000..fad987692f --- /dev/null +++ b/types/check-types/index.d.ts @@ -0,0 +1,162 @@ +// Type definitions for check-types 7.3 +// Project: https://github.com/philbooth/check-types.js +// Definitions by: idchlife +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped/ +// TypeScript Version: 2.2 + +type NegationFunction = (val: any) => boolean; + +type MaybeFunction = (val: T) => boolean | T; + +interface ArrayFunction { + (a: any): a is any[]; + + // TODO: Maybe there is a way to create type guards for array type checks + // Since syntax is like check.array.of.number(2) - it's not yet clear to me how this even works, so... + // I might use of: CheckType, but it will just return type guards for primitives and object type + // and will make variable simply non array type in conditionals. + of: { + [method: string]: boolean; + }; +} + +interface ArrayLikeFunction { + (a: any): a is ArrayLike; + + // See in array explanation of this type + of: { + [method: string]: boolean; + }; +} + +interface IterableFunction { + (a: any): a is Iterable; + + // See in array explanation of this type + of: { + [method: string]: boolean; + }; +} + +interface ObjectFunction { + (a: any): a is object; + + // See in array explanation of this type + of: { + [method: string]: boolean; + }; +} + +interface AssertFunction extends CheckType { + (possibleFalsy: T, message?: string, errorType?: { new(...args: any[]): any }): T; +} + +interface CheckType { + /* General predicates */ + + equal(a: any, b: any): boolean; + null(a: any): a is null; + undefined(a: any): a is undefined; + assigned(a: any): boolean; + primitive(a: any): a is number | string | boolean | null | undefined | symbol; + hasLength(a: any, length: number): boolean; + + /* String predicates */ + + string(a: any): a is string; + emptyString(a: string): boolean; + nonEmptyString(a: string): boolean; + contains(a: string, substring: string): boolean; + match(a: string, b: RegExp): boolean; + + /* Number predicates */ + + number(a: any): a is number; + integer(a: any): a is number; + zero(a: any): boolean; + infinity(a: any): boolean; + greater(num: number, greaterThan: number): boolean; + greaterOrEqual(num: number, greaterOrEqual: number): boolean; + less(num: number, lessThan: number): boolean; + lessOrEqual(num: number, lessOrEqual: number): boolean; + /** + * Excluding a and b. Any order of a, b + */ + between(num: number, a: number, b: number): boolean; + /** + * Including a, b. Any order of a, b + */ + inRange(num: number, a: number, b: number): boolean; + positive(num: number): boolean; + negative(num: number): boolean; + odd(num: number): boolean; + even(num: number): boolean; + + /* Boolean predicates */ + + boolean(a: any): a is boolean; + + /* Object predicates */ + + object: ObjectFunction; + emptyObject(a: object): boolean; + nonEmptyObject(a: object): boolean; + /** + * Checking via instanceof + */ + instanceStrict(a: any, prototype: T): a is T; + /** + * Checking via instanceof, fallback constructor.name and .toString() + */ + instance(a: any, prototype: T): a is T; + /** + * Duck type checking. Structural in other words. Checking if a has all properties of duck + */ + like(a: any, duck: T): a is T; + + /* Array predicates */ + + array: ArrayFunction; + emptyArray(a: any[]): boolean; + nonEmptyArray(a: any[]): boolean; + arrayLike: ArrayLikeFunction; + iterable: IterableFunction; + includes(a: any[], value: any): boolean; + + /* Date predicates */ + + date(a: any): a is Date; + + /* Function predicates */ + + function(a: any): a is (...args: any[]) => any; + + /* Modifiers (some of them in their respected sections) */ + not: CheckType & NegationFunction; + maybe: CheckType & MaybeFunction; + assert: AssertFunction; + + /* Batch operations */ + + /** + * Applying predicate to every element of array and returning resulting array + * + * Example: apply([2, 3, "four"], check.number) => [true, true, false] + */ + apply(arr: any[], predicate: (...args: any[]) => T): T[]; + + // Also some difficulties with returning object with only defined in predicates object propertis. + // Will gladly accept help or ideas. Now using any for returned object + map( + arr: T, + predicates: Partial<{ [k in keyof T]: (...args: any[]) => boolean }> + ): Partial<{ [k in keyof T]: any }>; + + all(arr: boolean[] | { [k: string]: boolean }): boolean; + + any(arr: boolean[] | { [k: string]: boolean }): boolean; +} + +declare const check: CheckType; + +export = check; diff --git a/types/check-types/tsconfig.json b/types/check-types/tsconfig.json new file mode 100644 index 0000000000..d3c89a7ac7 --- /dev/null +++ b/types/check-types/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "check-types-tests.ts" + ] +} \ No newline at end of file diff --git a/types/check-types/tslint.json b/types/check-types/tslint.json new file mode 100644 index 0000000000..2750cc0197 --- /dev/null +++ b/types/check-types/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } \ No newline at end of file