feat: first publish
commit
f586095b19
@ -0,0 +1,4 @@
|
|||||||
|
build/
|
||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
.DS_Store
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
# Swiss Army Knifey Ramda
|
||||||
|
|
||||||
|
Tools you could have gotten somewhere else, but you still decided to go this way.
|
||||||
|
|
||||||
|
## Ramda Compose With Promise
|
||||||
|
|
||||||
|
Added typings to composeWithPromise
|
||||||
|
|
||||||
|
```ts
|
||||||
|
it('should await and return a composed result', async function() {
|
||||||
|
const paramToProp = (param: string) => ({ param });
|
||||||
|
const sleepingSentence = (s: number) => async ({ param }: { param: string }) => {
|
||||||
|
const d1 = new Date();
|
||||||
|
await sleep(s, TimeUnit.second);
|
||||||
|
const d2 = new Date();
|
||||||
|
return `a_[${param}], slept for: ${d2.getTime() - d1.getTime()}`;
|
||||||
|
};
|
||||||
|
const toUp = async (param: string) => param.toUpperCase();
|
||||||
|
const removeStart = async (param: string) => param.slice(1);
|
||||||
|
const composed = composeWithPromise(
|
||||||
|
removeStart,
|
||||||
|
sleepingSentence(1),
|
||||||
|
paramToProp,
|
||||||
|
toUp,
|
||||||
|
sleepingSentence(2),
|
||||||
|
paramToProp
|
||||||
|
);
|
||||||
|
return expect(composed('hey')).to.eventually.match(/_\[A_\[HEY\], SLEPT FOR: \d{4}\], slept for: \d{3,4}$/g);
|
||||||
|
});
|
||||||
|
```
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "swiss-army-knifey-ramda",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "ramda utility functions",
|
||||||
|
"main": "build/src/index.js",
|
||||||
|
"types": "build/src/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rm -rf ./build",
|
||||||
|
"build": "npm run clean && tsc",
|
||||||
|
"test": "npm run build && NODE_ENV=test mocha --timeout 50000 --recursive ./build/test",
|
||||||
|
"start": "tsc && node ./build/index.js",
|
||||||
|
"serve": "tsc && NODE_ENV=production node ./build/index.js"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"env-replace": "./build/bin/envReplace.js",
|
||||||
|
"env-prepare": "./build/bin/envPrepare.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/gbili/saylo.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Guillermo Pages <mail@guillermo.at> (https://guillermo.at)",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/gbili/saylo/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/gbili/saylo#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/chai": "4.3.10",
|
||||||
|
"@types/chai-as-promised": "^7.1.8",
|
||||||
|
"@types/mocha": "10.0.4",
|
||||||
|
"@types/node": "^20.9.0",
|
||||||
|
"@types/ramda": "^0.29.8",
|
||||||
|
"@types/sinon": "^17.0.3",
|
||||||
|
"chai": "4.3.10",
|
||||||
|
"chai-as-promised": "^7.1.1",
|
||||||
|
"mocha": "^10.2.0",
|
||||||
|
"swiss-army-knifey": "^1.32.2",
|
||||||
|
"sinon": "^19.0.2"
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"test": "test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^8.0.0",
|
||||||
|
"ramda": "^0.30.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import { combineReturns, composeAccumulate, composeWithPromise, simpleCombineReturns } from './utils/ramda';
|
||||||
|
|
||||||
|
export { combineReturns, composeAccumulate, composeWithPromise, simpleCombineReturns };
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
import { composeWith } from "ramda";
|
||||||
|
|
||||||
|
export type AnyFunction<A extends any[] = any[], R = any> = (...args: A) => R;
|
||||||
|
|
||||||
|
export type ChainFunctionsExtractInputOutput<A extends any[], R> =
|
||||||
|
[AnyFunction<any, R>, ...AnyFunction[], AnyFunction<A, any>]
|
||||||
|
| [AnyFunction<A, R>];
|
||||||
|
|
||||||
|
export type UnboxIfArrayOfPromises<T> = T extends Promise<infer U>[] ? Promise<U[]> : T;
|
||||||
|
|
||||||
|
// Defines a generic function for composing functions with support for promises.
|
||||||
|
// `A` represents the argument types as a tuple, and `R` represents the return type.
|
||||||
|
export function composeWithPromise<A extends any[], R>(
|
||||||
|
// Uses a rest parameter to accept an array of functions. The function signatures are constrained by `ChainFunctionsExtractInputOutput`.
|
||||||
|
...fns: ChainFunctionsExtractInputOutput<A, R>
|
||||||
|
): (...args: A) => UnboxIfArrayOfPromises<R> { // Returns a function that takes arguments `A` and returns `R`, possibly unboxed from promises.
|
||||||
|
|
||||||
|
// Defines a function that conditionally unwraps promises in an array if `f` is the first function in the `fns` array.
|
||||||
|
// This is specifically used to handle the case where the last executed function (first in the reversed order) returns a promise or an array of promises.
|
||||||
|
const unboxIfLastFn = (f: AnyFunction) => (v: any) => fns[0] === f ? unboxPromisesInArray(f(v)) : f(v);
|
||||||
|
|
||||||
|
// A transformer function that applies each function in `fns` to the value, handling promises and arrays of promises.
|
||||||
|
const transformer = (f: AnyFunction, val: any) => {
|
||||||
|
// Wraps the function to automatically handle promise unboxing if it's the last function.
|
||||||
|
const wrappedFn = unboxIfLastFn(f);
|
||||||
|
|
||||||
|
// If `val` is a promise, await it before applying the wrapped function.
|
||||||
|
if (val && val.then) {
|
||||||
|
return val.then(wrappedFn);
|
||||||
|
// If `val` is an array of promises, await all promises in the array before applying the wrapped function.
|
||||||
|
} else if (isArrayOfPromises(val)) {
|
||||||
|
return Promise.all(val).then(wrappedFn);
|
||||||
|
}
|
||||||
|
// Otherwise, directly apply the wrapped function to `val`.
|
||||||
|
return wrappedFn(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a composed function that applies `transformer` across all functions in `fns`,
|
||||||
|
// effectively chaining them together in a manner that supports asynchronous operations.
|
||||||
|
return composeWith(transformer, fns);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility type for extracting and merging function parameter types
|
||||||
|
type AccumulateFunctions<T extends Array<Function>> = T extends [infer F, ...infer R]
|
||||||
|
? F extends (...args: any) => Promise<infer U> | infer U
|
||||||
|
? U & (R extends Array<Function> ? AccumulateFunctions<R> : {})
|
||||||
|
: never
|
||||||
|
: {};
|
||||||
|
|
||||||
|
type IsAnyAsyncFunction<T extends Array<Function>> = T extends [infer F, ...infer Rest]
|
||||||
|
? F extends (...args: any[]) => Promise<any>
|
||||||
|
? true
|
||||||
|
: IsAnyAsyncFunction<Rest extends Array<Function> ? Rest : []>
|
||||||
|
: false;
|
||||||
|
|
||||||
|
type UnboxPromise<T> = T extends Promise<infer U> ? U : T;
|
||||||
|
type IsPromise<T> = T extends Promise<any> ? true : false;
|
||||||
|
|
||||||
|
const accumulateAsync = async (acc: any, result: Promise<any>) => {
|
||||||
|
const awaitedResult = await result;
|
||||||
|
if (awaitedResult === undefined || awaitedResult === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return ({ ...acc, ...awaitedResult })
|
||||||
|
};
|
||||||
|
|
||||||
|
const accumulate = (acc: any, result: any) => {
|
||||||
|
if (result === undefined || result === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return ({ ...acc, ...result })
|
||||||
|
};
|
||||||
|
|
||||||
|
function accumulateGate(acc: any, result: any) {
|
||||||
|
if (result && result.then) {
|
||||||
|
return accumulateAsync(acc, result);
|
||||||
|
}
|
||||||
|
return accumulate(acc, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function composeAccumulate<T extends Array<(...args: any[]) => any>>(
|
||||||
|
...fns: T
|
||||||
|
) {
|
||||||
|
type ResultType = IsPromise<Parameters<T[0]>[0]> extends true ? Promise<UnboxPromise<Parameters<T[0]>[0]> & AccumulateFunctions<T>> : (UnboxPromise<Parameters<T[0]>[0]> & AccumulateFunctions<T>);
|
||||||
|
type IsAsync = IsAnyAsyncFunction<T> extends true ? true : (IsPromise<Parameters<T[0]>[0]> extends true ? true : false);
|
||||||
|
|
||||||
|
const accumulator = (initialArg: Parameters<T[0]>[0]): IsAsync extends true ? Promise<ResultType> : ResultType => {
|
||||||
|
return fns.reduce((acc: any, currFunc) => {
|
||||||
|
if (acc === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (acc && acc.then) {
|
||||||
|
const afterThen = acc.then(async (a: any) => {
|
||||||
|
if (a === undefined) return undefined;
|
||||||
|
return await accumulateGate(a, currFunc(a))
|
||||||
|
});
|
||||||
|
return afterThen;
|
||||||
|
}
|
||||||
|
return accumulateGate(acc, currFunc(acc));
|
||||||
|
}, initialArg);
|
||||||
|
};
|
||||||
|
|
||||||
|
return accumulator as IsAsync extends true
|
||||||
|
? (initialArg: Parameters<T[0]>[0]) => Promise<ResultType>
|
||||||
|
: (initialArg: Parameters<T[0]>[0]) => ResultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const isArrayOfPromises = function <T>(val: any): val is Promise<T>[] {
|
||||||
|
return Boolean(Array.isArray(val) && val.length && val[0] && val[0].then);
|
||||||
|
}
|
||||||
|
|
||||||
|
const unboxPromisesInArray = <T>(val: T) => isArrayOfPromises(val) ? Promise.all(val) : val;
|
||||||
|
|
||||||
|
export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
|
||||||
|
|
||||||
|
export type ReturnTypesOfArray<T extends Array<(...args: any) => any>> = {
|
||||||
|
[P in keyof T]: UnwrapPromise<ReturnType<T[P]>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UnionToIntersection<U> =
|
||||||
|
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||||
|
|
||||||
|
export type InferCombinedReturnType<T extends Array<(...args: any) => any>> = UnionToIntersection<ReturnTypesOfArray<T>[number]>;
|
||||||
|
|
||||||
|
export async function simpleCombineReturns<T extends Array<(arg: U) => any>, U>(
|
||||||
|
functionArray: [...T],
|
||||||
|
input: U
|
||||||
|
): Promise<InferCombinedReturnType<T>> {
|
||||||
|
const results = await Promise.all(functionArray.map((func) => func(input)));
|
||||||
|
return Object.assign({}, ...results);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SameArgumentType<T> = T extends Array<(arg: infer U) => any> ? U : never;
|
||||||
|
|
||||||
|
export function combineReturns<T extends Array<(arg: any) => any>>(
|
||||||
|
functionArray: [...T]
|
||||||
|
): <U extends SameArgumentType<T>>(input: U) => Promise<InferCombinedReturnType<T>> {
|
||||||
|
return async <U extends SameArgumentType<T>>(input: U) => {
|
||||||
|
const results = await Promise.all(functionArray.map((func) => func(input)));
|
||||||
|
return Object.assign({}, ...results) as InferCombinedReturnType<T>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
import chai from 'chai';
|
||||||
|
import chaiAsPromised from 'chai-as-promised';
|
||||||
|
|
||||||
|
chai.use(chaiAsPromised);
|
||||||
@ -0,0 +1,205 @@
|
|||||||
|
import { expect } from 'chai';
|
||||||
|
import chai from 'chai';
|
||||||
|
import chaiAsPromised from 'chai-as-promised';
|
||||||
|
import { toString } from 'ramda';
|
||||||
|
import { arraySum, getArrayFromZeroOfLengthN, sleep, TimeUnit } from 'swiss-army-knifey';
|
||||||
|
import { combineReturns, composeWithPromise, simpleCombineReturns } from '../../src/utils/ramda';
|
||||||
|
|
||||||
|
chai.use(chaiAsPromised);
|
||||||
|
|
||||||
|
describe(`ramda style`, function() {
|
||||||
|
describe(`composeWithPromise(few functions)`, function() {
|
||||||
|
|
||||||
|
it('should await and return a composed result', async function() {
|
||||||
|
const paramToProp = (param: string) => ({ param });
|
||||||
|
const sleepingSentence = (s: number) => async ({ param }: { param: string }) => {
|
||||||
|
const d1 = new Date();
|
||||||
|
await sleep(s, TimeUnit.second);
|
||||||
|
const d2 = new Date();
|
||||||
|
return `a_[${param}], slept for: ${d2.getTime() - d1.getTime()}`;
|
||||||
|
};
|
||||||
|
const toUp = async (param: string) => param.toUpperCase();
|
||||||
|
const removeStart = async (param: string) => param.slice(1);
|
||||||
|
const composed = composeWithPromise(
|
||||||
|
removeStart,
|
||||||
|
sleepingSentence(1),
|
||||||
|
paramToProp,
|
||||||
|
toUp,
|
||||||
|
sleepingSentence(2),
|
||||||
|
paramToProp
|
||||||
|
);
|
||||||
|
return expect(composed('hey')).to.eventually.match(/_\[A_\[HEY\], SLEPT FOR: \d{4}\], slept for: \d{3,4}$/g);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to compose non async functions', async function() {
|
||||||
|
const paramToProp = (param: string) => ({ param });
|
||||||
|
const toUp = (param: string) => param.toUpperCase();
|
||||||
|
const removeFirst = ({ param }: { param: string }) => param.slice(1);
|
||||||
|
const composed = composeWithPromise(
|
||||||
|
removeFirst,
|
||||||
|
paramToProp,
|
||||||
|
toUp,
|
||||||
|
toString
|
||||||
|
);
|
||||||
|
return expect(composed(3.14159)).to.equal('.14159');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle arrays of promises', async function() {
|
||||||
|
// [1, 2, 3] -> [Promise 1, Promise 4, Promise 9]
|
||||||
|
const asyncSquare = (ns: number[]) => {
|
||||||
|
return ns.map(async n => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return n * n;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
// [1, 4, 9] -> [0, 6, 45]
|
||||||
|
const asyncSum = (ns: number[]) => {
|
||||||
|
return ns
|
||||||
|
// [1, 4, 9]
|
||||||
|
.map(getArrayFromZeroOfLengthN)
|
||||||
|
// [[0], [0, 1, 2, 3], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
|
||||||
|
.map(async (arr: number[]) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return arraySum(arr);
|
||||||
|
});
|
||||||
|
// [0, 6, 36]
|
||||||
|
};
|
||||||
|
const composed = composeWithPromise(
|
||||||
|
asyncSum,
|
||||||
|
asyncSquare,
|
||||||
|
);
|
||||||
|
|
||||||
|
return expect(composed([1, 2, 3])).to.eventually.deep.equal([0, 6, 36]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle rejections', async function() {
|
||||||
|
// [1, 2, 3] -> [Promise 1, Promise 4, Promise 9]
|
||||||
|
const asyncSquare = (ns: number[]) => {
|
||||||
|
return ns.map(async n => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return n * n;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
// [1, 4, 9] -> [0, 6, 45]
|
||||||
|
const asyncSum = (ns: number[]) => {
|
||||||
|
return ns
|
||||||
|
// [1, 4, 9]
|
||||||
|
.map(getArrayFromZeroOfLengthN)
|
||||||
|
// [[0], [0, 1, 2, 3], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
|
||||||
|
.map(async (arr: number[]) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
throw new Error('Woho rejected promise');
|
||||||
|
});
|
||||||
|
// [0, 6, 36]
|
||||||
|
};
|
||||||
|
|
||||||
|
const composed = composeWithPromise(
|
||||||
|
asyncSum,
|
||||||
|
asyncSquare,
|
||||||
|
);
|
||||||
|
|
||||||
|
return expect(composed([1, 2, 3])).to.eventually.be.rejectedWith('Woho rejected promise');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('simpleCombineReturns', () => {
|
||||||
|
|
||||||
|
it('should combine results of promise-returning functions with sleep delay', async () => {
|
||||||
|
const fn1 = async (num: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { value1: num + 1 };
|
||||||
|
};
|
||||||
|
const fn2 = async (num: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { value2: num * 2 };
|
||||||
|
};
|
||||||
|
|
||||||
|
const startTime = Date.now();
|
||||||
|
const result = await simpleCombineReturns([fn1, fn2], 10);
|
||||||
|
const endTime = Date.now();
|
||||||
|
|
||||||
|
expect(result).to.deep.equal({ value1: 11, value2: 20 });
|
||||||
|
expect(endTime - startTime).to.be.greaterThan(1000); // Check that at least 1 second has passed
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should combine results of functions taking string inputs', async () => {
|
||||||
|
const fn1 = async (str: string) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { upper: str.toUpperCase() };
|
||||||
|
};
|
||||||
|
const fn2 = async (str: string) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { length: str.length };
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await simpleCombineReturns([fn1, fn2], "test");
|
||||||
|
expect(result).to.deep.equal({ upper: "TEST", length: 4 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should combine results of functions returning different types', async () => {
|
||||||
|
const fn1 = async (value: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { boolValue: value > 10 };
|
||||||
|
};
|
||||||
|
const fn2 = async (value: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { stringValue: `Value is ${value}` };
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await simpleCombineReturns([fn1, fn2], 15);
|
||||||
|
expect(result).to.deep.equal({ boolValue: true, stringValue: "Value is 15" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('combineReturns', () => {
|
||||||
|
it('should combine results of curried promise-returning functions with sleep delay', async () => {
|
||||||
|
const fn1 = async (num: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { value1: num + 1 };
|
||||||
|
};
|
||||||
|
const fn2 = async (num: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { value2: num * 2 };
|
||||||
|
};
|
||||||
|
|
||||||
|
const combined = combineReturns([fn1, fn2]);
|
||||||
|
const startTime = Date.now();
|
||||||
|
const result = await combined(10);
|
||||||
|
const endTime = Date.now();
|
||||||
|
|
||||||
|
expect(result).to.deep.equal({ value1: 11, value2: 20 });
|
||||||
|
expect(endTime - startTime).to.be.greaterThan(1000); // Check that at least 1 second has passed
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should combine results of curried functions taking string inputs', async () => {
|
||||||
|
const fn1 = async (str: string) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { upper: str.toUpperCase() };
|
||||||
|
};
|
||||||
|
const fn2 = async (str: string) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { length: str.length };
|
||||||
|
};
|
||||||
|
|
||||||
|
const combined = combineReturns([fn1, fn2]);
|
||||||
|
const result = await combined("test");
|
||||||
|
expect(result).to.deep.equal({ upper: "TEST", length: 4 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should combine results of curried functions returning different types', async () => {
|
||||||
|
const fn1 = async (value: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { boolValue: value > 10 };
|
||||||
|
};
|
||||||
|
const fn2 = async (value: number) => {
|
||||||
|
await sleep(1, TimeUnit.second);
|
||||||
|
return { stringValue: `Value is ${value}` };
|
||||||
|
};
|
||||||
|
|
||||||
|
const combined = combineReturns([fn1, fn2]);
|
||||||
|
const result = await combined(15);
|
||||||
|
expect(result).to.deep.equal({ boolValue: true, stringValue: "Value is 15" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||||
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
|
"lib": ["ES2015", "DOM"], /* Specify library files to be included in the compilation. */
|
||||||
|
"allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
|
"checkJs": true, /* Report errors in .js files. */
|
||||||
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
|
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
|
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
|
"outDir": "./build/", /* Redirect output structure to the directory. */
|
||||||
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
// "composite": true, /* Enable project compilation */
|
||||||
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
// "removeComments": true, /* Do not emit comments to output. */
|
||||||
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
|
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||||
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
|
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
|
||||||
|
/* Strict Type-Checking Options */
|
||||||
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
|
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
|
"strictNullChecks": true, /* Enable strict null checks. */
|
||||||
|
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
|
"strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
|
"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
|
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
|
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
|
/* Additional Checks */
|
||||||
|
"noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
|
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
|
||||||
|
/* Module Resolution Options */
|
||||||
|
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
|
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
|
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
|
/* Source Map Options */
|
||||||
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
|
||||||
|
/* Experimental Options */
|
||||||
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
|
||||||
|
/* Advanced Options */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import * as R from "ramda";
|
||||||
|
|
||||||
|
declare module "ramda" {
|
||||||
|
export function composeWith<TArgs extends any[], TResult, T extends (fn: (...args: any[]) => any, intermediateResult: any) => any>
|
||||||
|
(transformer: T extends (fn: (...args: any[]) => any, intermediateResult: any) => infer Z ? (fn: (...args: any[]) => any, intermediateResult: any) => Z : never, fns: R.AtLeastOneFunctionsFlowFromRightToLeft<TArgs, TResult>): (...args: TArgs) => ReturnType<T>;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue