From f64b56300b44fce33b6767cf495164cdb1e95134 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Mon, 13 Jul 2020 12:12:12 +0300 Subject: [PATCH] Add TypeScript infrastructure and typings --- package-lock.json | 175 +++++++++++++++++++++++++++++++ package.json | 15 ++- types/.eslintrc.js | 16 +++ types/common.d.ts | 1 + types/lib/iterator.d.ts | 227 ++++++++++++++++++++++++++++++++++++++++ types/tsconfig.json | 14 +++ 6 files changed, 443 insertions(+), 5 deletions(-) create mode 100644 types/.eslintrc.js create mode 100644 types/common.d.ts create mode 100644 types/lib/iterator.d.ts create mode 100644 types/tsconfig.json diff --git a/package-lock.json b/package-lock.json index d8030854..6eae4d07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1037,6 +1037,166 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz", + "integrity": "sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "3.6.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.0.tgz", + "integrity": "sha512-4Vdf2hvYMUnTdkCNZu+yYlFtL2v+N2R7JOynIOkFbPjf9o9wQvRwRkzUdWlFd2YiiUwJLbuuLnl5civNg5ykOQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/types": "3.6.0", + "@typescript-eslint/typescript-estree": "3.6.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.0.tgz", + "integrity": "sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "3.6.0", + "@typescript-eslint/types": "3.6.0", + "@typescript-eslint/typescript-estree": "3.6.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/types": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.0.tgz", + "integrity": "sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.0.tgz", + "integrity": "sha512-G57NDSABHjvob7zVV09ehWyD1K6/YUKjz5+AufObFyjNO4DVmKejj47MHjVHHlZZKgmpJD2yyH9lfCXHrPITFg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "3.6.0", + "@typescript-eslint/visitor-keys": "3.6.0", + "debug": "^4.1.1", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz", + "integrity": "sha512-p1izllL2Ubwunite0ITjubuMQRBGgjdVYwyG7lXPX8GbrA6qF0uwSRz9MnXZaHMxID4948gX0Ez8v9tUDi/KfQ==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, "acorn": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", @@ -4581,6 +4741,15 @@ "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "dev": true }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -4596,6 +4765,12 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, + "typescript": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz", + "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==", + "dev": true + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", diff --git a/package.json b/package.json index 1396bd99..16382ff4 100644 --- a/package.json +++ b/package.json @@ -32,16 +32,18 @@ "dist/lib/network.js": false, "dist/lib/stream.js": false }, + "types": "./types/common.d.ts", "readmeFilename": "README.md", "files": [ "common.mjs", "lib/", - "dist/" + "dist/", + "types/" ], "scripts": { - "test": "npm run -s lint && metatests test/ && for test in ./sequential-test/*.js; do metatests \"$test\"; done", - "lint": "eslint . && prettier -c \"**/*.js\" \"**/*.json\" \"**/*.md\" \".*rc\" \"**/*.yml\"", - "fmt": "prettier --write \"**/*.js\" \"**/*.json\" \"**/*.md\" \".*rc\" \"**/*.yml\"", + "test": "npm run -s lint && tsc -p types/tsconfig.json && metatests test/ && for test in ./sequential-test/*.js; do metatests \"$test\"; done", + "lint": "eslint . && prettier -c \"**/*.js\" \"**/*.json\" \"**/*.md\" \".*rc\" \"**/*.yml\" \"**/*.d.ts\"", + "fmt": "prettier --write \"**/*.js\" \"**/*.json\" \"**/*.md\" \".*rc\" \"**/*.yml\" \"**/*.d.ts\"", "doc": "metadoc", "build": "babel common.js -d dist && babel lib -d dist/lib && node tools/esmodules-export-gen.js", "prepublish": "npm run -s build" @@ -54,12 +56,15 @@ "@babel/core": "^7.10.2", "@babel/preset-env": "^7.10.2", "@metarhia/doc": "^0.6.1", + "@typescript-eslint/eslint-plugin": "^3.6.0", + "@typescript-eslint/parser": "^3.6.0", "eslint": "^6.8.0", "eslint-config-metarhia": "^7.0.1", "eslint-config-prettier": "^6.11.0", "eslint-plugin-import": "^2.20.2", "eslint-plugin-prettier": "^3.1.3", "metatests": "^0.7.1", - "prettier": "1.19.x" + "prettier": "1.19.x", + "typescript": "^3.9.6" } } diff --git a/types/.eslintrc.js b/types/.eslintrc.js new file mode 100644 index 00000000..f84e3d44 --- /dev/null +++ b/types/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'prettier'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-types': 'off', + // This rule doesn't work correctly without a special plugin for TS. + 'import/no-unresolved': 'off', + }, +}; diff --git a/types/common.d.ts b/types/common.d.ts new file mode 100644 index 00000000..14a3a0be --- /dev/null +++ b/types/common.d.ts @@ -0,0 +1 @@ +export * from './lib/iterator'; diff --git a/types/lib/iterator.d.ts b/types/lib/iterator.d.ts new file mode 100644 index 00000000..c745f674 --- /dev/null +++ b/types/lib/iterator.d.ts @@ -0,0 +1,227 @@ +type UnionToIntersection = (Union extends any +? (argument: Union) => void +: never) extends (argument: infer Intersection) => void + ? Intersection + : never; + +type IteratorToObjectResult = UnionToIntersection< + T extends [infer K, infer V] + ? K extends PropertyKey + ? Record + : IteratorToAnyObjectResult + : IteratorToAnyObjectResult +>; + +type IteratorToAnyObjectResult = T extends [keyof any, infer V] + ? Record + : never; + +type FlatIterator1 = T extends Iterable ? Iterator : never; + +type FlatIterator2 = T extends Iterable> + ? Iterator + : never; + +type FlatIterator3 = T extends Iterable>> + ? Iterator + : never; + +type ChainApplyReturn = Iterator ? U : never>; + +type CollectTo = T extends readonly [infer K, infer V] + ? C extends Map + ? Map + : C + : C; + +export class Iterator implements IterableIterator { + constructor(base: Iterable); + + public [Symbol.iterator](): IterableIterator; + + public next(): IteratorResult; + + public count(): number; + + public each(fn: (arg: T) => void): void; + + public each(fn: (this: U, arg: T) => void, thisArg: U): void; + + public forEach(fn: (arg: T) => void): void; + + public forEach(fn: (this: U, arg: T) => void, thisArg: U): void; + + public every(fn: (arg: T) => boolean): boolean; + public every(fn: (this: U, arg: T) => boolean, thisArg: U): boolean; + + public find(fn: (arg: T) => boolean): T | undefined; + public find(fn: (this: U, arg: T) => boolean, thisArg: U): T | undefined; + + public includes(element: T): boolean; + + public reduce(reducer: (acc: U, value: T) => U, initialValue: U): U; + public reduce(reducer: (acc: T, value: T) => T): T; + + public some(fn: (arg: T) => boolean): boolean; + public some(fn: (this: U, arg: T) => boolean, thisArg: U): boolean; + + public someCount(fn: (arg: T) => boolean, count: number): boolean; + public someCount( + fn: (this: U, arg: T) => boolean, + count: number, + thisArg: U + ): boolean; + public collectTo( + CollectionClass: new (iterable: Iterable) => CollectTo + ): CollectTo; + public collectWith(obj: U, collector: (acc: U, value: T) => void): U; + + public toArray(): T[]; + + public toObject(): IteratorToObjectResult; + + public map(mapper: (arg: T) => U): Iterator; + public map(mapper: (this: V, arg: T) => U, thisArg: V): Iterator; + public filter(predicate: (arg: T) => arg is S): Iterator; + public filter(predicate: (arg: T) => boolean): Iterator; + public filter( + predicate: (arg: T) => arg is S, + thisArg: U + ): Iterator; + public filter( + predicate: (this: U, arg: T) => boolean, + thisArg: U + ): Iterator; + public filterMap( + mapper: (this: V, arg: T) => U | W, + thisArg: V, + filterValue: W + ): Iterator; + public filterMap( + mapper: (this: V, arg: T) => U | undefined, + thisArg: V + ): Iterator; + public filterMap(mapper: (arg: T) => U | undefined): Iterator; + public flat(depth: 0): Iterator; + public flat(depth?: 1): FlatIterator1; + public flat(depth: 2): FlatIterator2; + public flat(depth: 3): FlatIterator3; + public flat(depth: number): Iterator; + + public flatMap(mapper: (arg: T) => Iterable): Iterator; + public flatMap( + mapper: (this: V, arg: T) => Iterable, + thisArg: V + ): Iterator; + + public zip(iterator: Iterable): Iterator<[T, U]>; + public zip( + ...iterators: [Iterable, Iterable] + ): Iterator<[T, U, V]>; + public zip( + ...iterators: [Iterable, Iterable, Iterable] + ): Iterator<[T, U, V, W]>; + public zip(...iterators: Array>): Iterator; + + // Replace manual types with variadic tuple when TS 4.0 is released. + // https://github.com/microsoft/TypeScript/pull/39094 + // public static zip>( + // ...iterators: U + // ): Iterator<[T, ...U]>; + + public chain(it: Iterable): Iterator; + public chain(...iterators: Array>): Iterator; + + public take(amount: number): Iterator; + + public takeWhile(predicate: (arg: T) => boolean): Iterator; + public takeWhile( + predicate: (this: U, arg: T) => boolean, + thisArg: U + ): Iterator; + + public skip(amount: number): Iterator; + + public skipWhile(predicate: (arg: T) => boolean): Iterator; + public skipWhile( + predicate: (this: U, arg: T) => boolean, + thisArg: U + ): Iterator; + + public enumerate(): Iterator<[number, T]>; + + public min(): T | undefined; + public min(accessor: (arg: T) => K): T | undefined; + public min(accessor: (this: U, arg: T) => K, thisArg: U): T | undefined; + + public max(): T | undefined; + public max(accessor: (arg: T) => K): T | undefined; + public max(accessor: (this: U, arg: T) => K, thisArg: U): T | undefined; + + public findCompare( + comparator: (this: U, arg1: K, arg2: K) => boolean, + accessor: (this: U, arg: T) => K, + thisArg: U + ): T | undefined; + public findCompare( + comparator: (arg1: K, arg2: K) => boolean, + accessor: (arg: T) => K + ): T | undefined; + public findCompare(comparator: (arg1: T, arg2: T) => boolean): T | undefined; + + public partition(predicate: (arg: T) => boolean): [T[], T[]]; + public partition( + predicate: (arg: T) => boolean + ): [L[], R[]]; + public partition(predicate: (arg: T) => number): Array; + public partition( + predicate: (this: U, arg: T) => number, + thisArg: U + ): Array; + + public groupBy(classifier: (arg: T) => K): Map; + public groupBy( + classifier: (this: U, arg: T) => K, + thisArg: U + ): Map; + + public join(sep?: string, prefix?: string, suffix?: string): string; + + public apply(fn: (arg: Iterator) => R): R; + + public chainApply(fn: (arg: Iterator) => R): ChainApplyReturn; + + public static range( + start: number, + stop?: number, + step?: number + ): Iterator; + + public static zip( + base: Iterable, + iterator: Iterable + ): Iterator<[T, U]>; + public static zip( + ...iterators: [Iterable, Iterable, Iterable] + ): Iterator<[T, U, V]>; + public static zip( + ...iterators: [Iterable, Iterable, Iterable, Iterable] + ): Iterator<[T, U, V, W]>; + + // Replace manual types with variadic tuple when TS 4.0 is released. + // https://github.com/microsoft/TypeScript/pull/39094 + // public static zip>( + // base: Iterable, + // ...iterators: U + // ): Iterator<[T, ...U]>; +} + +export function iter(base: Iterable): Iterator; + +export function iterEntries( + obj: T +): Iterator<[keyof T, T[keyof T]]>; + +export function iterKeys(obj: T): Iterator; + +export function iterValues(obj: T): Iterator; diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 00000000..f5712549 --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "strict": true, + "experimentalDecorators": true, + "noEmit": true, + "baseUrl": ".", + "preserveWatchOutput": true, + "paths": { + "*": ["../node_modules/*"] + } + }, + "include": ["lib/**/*.d.ts"] +}