人心就是立国的大根本。——孙中山
问题:
/*
Intro:
For some unknown reason most of our developers left
the company. We need to actively hire now.
In the media we've read that companies that invent
and publish new technologies attract more potential
candidates. We need to use this opportunity and
invent and publish some npm packages. Following the
new trend of functional programming in JS we
decided to develop a functional utility library.
This will put us on the bleading edge since we are
pretty much sure no one else did anything similar.
We also provided some jsdoc along with the
functions, but it might sometimes be inaccurate.
Exercise:
Provide proper typing for the specified functions.
Bonus:
Could you please also refactor the code to reduce
code duplication?
You might need some excessive type casting to make
it really short.
*/
/**
* 2 arguments passed: returns a new array
* which is a result of input being mapped using
* the specified mapper.
*
* 1 argument passed: returns a function which accepts
* an input and returns a new array which is a result
* of input being mapped using original mapper.
*
* 0 arguments passed: returns itself.
*
* @param {Function} mapper
* @param {Array} input
* @return {Array | Function}
*/
export function map(mapper, input) {
if (arguments.length === 0) {
return map;
}
if (arguments.length === 1) {
return function subFunction(subInput) {
if (arguments.length === 0) {
return subFunction;
}
return subInput.map(mapper);
};
}
return input.map(mapper);
}
/**
* 2 arguments passed: returns a new array
* which is a result of input being filtered using
* the specified filter function.
*
* 1 argument passed: returns a function which accepts
* an input and returns a new array which is a result
* of input being filtered using original filter
* function.
*
* 0 arguments passed: returns itself.
*
* @param {Function} filterer
* @param {Array} input
* @return {Array | Function}
*/
export function filter(filterer, input) {
if (arguments.length === 0) {
return filter;
}
if (arguments.length === 1) {
return function subFunction(subInput) {
if (arguments.length === 0) {
return subFunction;
}
return subInput.filter(filterer);
};
}
return input.filter(filterer);
}
/**
* 3 arguments passed: reduces input array it using the
* specified reducer and initial value and returns
* the result.
*
* 2 arguments passed: returns a function which accepts
* input array and reduces it using previously specified
* reducer and initial value and returns the result.
*
* 1 argument passed: returns a function which:
* * when 2 arguments is passed to the subfunction, it
* reduces the input array using specified initial
* value and previously specified reducer and returns
* the result.
* * when 1 argument is passed to the subfunction, it
* returns a function which expects the input array
* and reduces the specified input array using
* previously specified reducer and inital value.
* * when 0 argument is passed to the subfunction, it
* returns itself.
*
* 0 arguments passed: returns itself.
*
* @param {Function} reducer
* @param {*} initialValue
* @param {Array} input
* @return {* | Function}
*/
export function reduce(reducer, initialValue, input) {
if (arguments.length === 0) {
return reduce;
}
if (arguments.length === 1) {
return function subFunction(subInitialValue, subInput) {
if (arguments.length === 0) {
return subFunction;
}
if (arguments.length === 1) {
return function subSubFunction(subSubInput) {
if (arguments.length === 0) {
return subSubFunction;
}
return subSubInput.reduce(reducer, subInitialValue);
};
}
return subInput.reduce(reducer,subInitialValue);
}
}
if (arguments.length === 2) {
return function subFunction(subInput) {
if (arguments.length === 0) {
return subFunction;
}
return subInput.reduce(reducer, initialValue);
};
}
return input.reduce(reducer, initialValue);
}
/**
* 2 arguments passed: returns sum of a and b.
*
* 1 argument passed: returns a function which expects
* b and returns sum of a and b.
*
* 0 arguments passed: returns itself.
*
* @param {Number} a
* @param {Number} b
* @return {Number | Function}
*/
export function add(a, b) {
if (arguments.length === 0) {
return add;
}
if (arguments.length === 1) {
return function subFunction(subB) {
if (arguments.length === 0) {
return subFunction;
}
return a + subB;
};
}
return a + b;
}
/**
* 2 arguments passed: subtracts b from a and
* returns the result.
*
* 1 argument passed: returns a function which expects
* b and subtracts b from a and returns the result.
*
* 0 arguments passed: returns itself.
*
* @param {Number} a
* @param {Number} b
* @return {Number | Function}
*/
export function subtract(a, b) {
if (arguments.length === 0) {
return subtract;
}
if (arguments.length === 1) {
return function subFunction(subB) {
if (arguments.length === 0) {
return subFunction;
}
return a - subB;
};
}
return a - b;
}
/**
* 2 arguments passed: returns value of property
* propName of the specified object.
*
* 1 argument passed: returns a function which expects
* propName and returns value of property propName
* of the specified object.
*
* 0 arguments passed: returns itself.
*
* @param {Object} obj
* @param {String} propName
* @return {* | Function}
*/
export function prop(obj, propName) {
if (arguments.length === 0) {
return prop;
}
if (arguments.length === 1) {
return function subFunction(subPropName) {
if (arguments.length === 0) {
return subFunction;
}
return obj[subPropName];
};
}
return obj[propName];
}
/**
* >0 arguments passed: expects each argument to be
* a function. Returns a function which accepts the
* same arguments as the first function. Passes these
* arguments to the first function, the result of
* the first function passes to the second function,
* the result of the second function to the third
* function... and so on. Returns the result of the
* last function execution.
*
* 0 arguments passed: returns itself.
*
* TODO TypeScript
* * Should properly handle at least 5 arguments.
* * Should also make sure argument of the next
* function matches the return type of the previous
* function.
*
* @param {Function[]} functions
* @return {*}
*/
export function pipe(...functions) {
if (arguments.length === 0) {
return pipe;
}
return function subFunction() {
let nextArguments = Array.from(arguments);
let result;
for (const func of functions) {
result = func(...nextArguments);
nextArguments = [result];
}
return result;
};
}
报错:
index.ts(46,21): error TS7006: Parameter 'mapper' implicitly has an 'any' type.
index.ts(46,29): error TS7006: Parameter 'input' implicitly has an 'any' type.
index.ts(51,37): error TS7006: Parameter 'subInput' implicitly has an 'any' type.
index.ts(77,24): error TS7006: Parameter 'filterer' implicitly has an 'any' type.
index.ts(77,34): error TS7006: Parameter 'input' implicitly has an 'any' type.
index.ts(82,37): error TS7006: Parameter 'subInput' implicitly has an 'any' type.
index.ts(120,24): error TS7006: Parameter 'reducer' implicitly has an 'any' type.
index.ts(120,33): error TS7006: Parameter 'initialValue' implicitly has an 'any' type.
index.ts(120,47): error TS7006: Parameter 'input' implicitly has an 'any' type.
index.ts(125,37): error TS7006: Parameter 'subInitialValue' implicitly has an 'any' type.
index.ts(125,54): error TS7006: Parameter 'subInput' implicitly has an 'any' type.
index.ts(130,48): error TS7006: Parameter 'subSubInput' implicitly has an 'any' type.
index.ts(141,37): error TS7006: Parameter 'subInput' implicitly has an 'any' type.
index.ts(163,21): error TS7006: Parameter 'a' implicitly has an 'any' type.
index.ts(163,24): error TS7006: Parameter 'b' implicitly has an 'any' type.
index.ts(168,37): error TS7006: Parameter 'subB' implicitly has an 'any' type.
index.ts(191,26): error TS7006: Parameter 'a' implicitly has an 'any' type.
index.ts(191,29): error TS7006: Parameter 'b' implicitly has an 'any' type.
index.ts(196,37): error TS7006: Parameter 'subB' implicitly has an 'any' type.
index.ts(220,22): error TS7006: Parameter 'obj' implicitly has an 'any' type.
index.ts(220,27): error TS7006: Parameter 'propName' implicitly has an 'any' type.
index.ts(225,37): error TS7006: Parameter 'subPropName' implicitly has an 'any' type.
index.ts(256,17): error TS7023: 'pipe' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
index.ts(256,22): error TS7019: Rest parameter 'functions' implicitly has an 'any[]' type.
test.ts(4,20): error TS2554: Expected 2 arguments, but got 0.
test.ts(5,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(8,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(10,23): error TS2554: Expected 3 arguments, but got 0.
test.ts(11,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(14,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(17,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(20,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(22,23): error TS2554: Expected 2 arguments, but got 0.
test.ts(23,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(26,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(28,20): error TS2554: Expected 2 arguments, but got 0.
test.ts(29,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(32,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(34,25): error TS2554: Expected 2 arguments, but got 0.
test.ts(35,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(38,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(40,21): error TS2554: Expected 2 arguments, but got 0.
test.ts(41,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(44,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(46,26): error TS2554: Expected 2 arguments, but got 1.
test.ts(46,43): error TS2554: Expected 2 arguments, but got 1.
test.ts(46,56): error TS2554: Expected 3 arguments, but got 2.
test.ts(47,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(49,30): error TS2554: Expected 2 arguments, but got 1.
test.ts(49,47): error TS2554: Expected 2 arguments, but got 1.
test.ts(50,12): error TS2344: Type 'false' does not satisfy the constraint 'true'.
答案: