Skip to content

Commit

Permalink
feat: improve type safety
Browse files Browse the repository at this point in the history
  • Loading branch information
Planeshifter committed Oct 14, 2024
1 parent 2b2dd25 commit ce44167
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,57 @@
* var out = bar( 1, 2, 3 );
* // returns [ 2, 4, 6 ]
*/
declare function mapArguments<T = unknown>( fcn: ( ...args: Array<T> ) => Array<T>, clbk: ( arg: T ) => T, thisArg?: unknown ): ( ...args: Array<T> ) => Array<T>;
declare function mapArguments<
T extends ( ...args: Array<any> ) => any,
C extends ( this: ThisParameterType<T>, value: Parameters<T>[number], index: number ) => any
>(
fcn: T,
clbk: C
): ( ...args: Parameters<T> ) => ReturnType<T>;

/**
* Returns a function that applies arguments to a provided function after transforming arguments according to a callback function.
*
* ## Notes
*
* - The callback function is provided the following arguments:
*
* - **value**: argument value.
* - **index**: argument index.
*
* @param fcn - input function
* @param clbk - callback function
* @param thisArg - input function context
* @returns function wrapper
*
* @example
* function foo( a, b, c ) {
* return [ a, b, c ];
* }
*
* function clbk( v ) {
* this.count += 1;
* return v * 2;
* }
*
* var thisArg = { 'count': 0 };
* var bar = mapArguments( foo, clbk, thisArg );
*
* var out = bar( 1, 2, 3 );
* // returns [ 2, 4, 6 ]
*
* var count = thisArg.count;
* // returns 3
*/
declare function mapArguments<
T extends ( ...args: Array<any> ) => any,
C extends ( this: ThisParameterType<T>, value: Parameters<T>[number], index: number ) => any,
ThisArg
>(
fcn: T,
clbk: C,
thisArg: ThisArg
): ( this: ThisArg, ...args: Parameters<T> ) => ReturnType<T>;


// EXPORTS //
Expand Down
62 changes: 38 additions & 24 deletions lib/node_modules/@stdlib/utils/map-arguments/docs/types/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,37 @@

import mapArguments = require( './index' );

/**
* Callback function.
*
* @param v - argument
* @returns result
*/
// FUNCTIONS //

function clbk<T>( v: T ): T {
return v;
}

function stringify( n: number ): string {
return n.toString();
}

function sum( ...numbers: Array<number> ): number {
return numbers.reduce( ( a, b ) => a + b, 0 );
}

function greet( this: { name: string }, greeting: string ): string {
return `${greeting}, ${this.name}!`; // eslint-disable-line no-invalid-this
}


// TESTS //

// The function returns a function...
{
mapArguments<number>( ( x, y, z ): Array<number> => [ x, y, z ], clbk ); // $ExpectType (...args: number[]) => number[]
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], clbk, {} ); // $ExpectType (...args: string[]) => string[]
mapArguments( ( x: number, y: number, z: number ): Array<number> => [ x, y, z ], clbk ); // $ExpectType (x: number, y: number, z: number) => number[]
mapArguments( ( x: string, y: string, z: string ): Array<string> => [ x, y, z ], clbk, {} ); // $ExpectType (this: {}, x: string, y: string, z: string) => string[]
mapArguments( ( x: number, y: number ): number => x + y, clbk ); // $ExpectType (x: number, y: number) => number

mapArguments( stringify, ( x: number ) => x * 2 ); // $ExpectType (n: number) => string
mapArguments( sum, ( x: number ) => x * 2 ); // $ExpectType (...args: number[]) => number

mapArguments( greet, ( s: string ) => s.toUpperCase(), { 'name': 'World' } ); // $ExpectType (this: { name: string; }, greeting: string) => string
}

// The compiler throws an error if the function is provided a first argument other than a function...
Expand All @@ -56,24 +70,24 @@ function clbk<T>( v: T ): T {

// The compiler throws an error if the function is provided a second argument other than a function...
{
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], '5' ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], true ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], false ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], 123 ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], null ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], [] ); // $ExpectError

mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], '5', {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], true, {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], false, {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], 123, {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], null, {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], {}, {} ); // $ExpectError
mapArguments<string>( ( x, y, z ): Array<string> => [ x, y, z ], [], {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], '5' ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], true ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], false ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], 123 ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], null ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], [] ); // $ExpectError

mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], '5', {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], true, {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], false, {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], 123, {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], null, {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], {}, {} ); // $ExpectError
mapArguments( ( x, y, z ): Array<string> => [ x, y, z ], [], {} ); // $ExpectError
}

// The compiler throws an error if the function is provided more than three arguments...
{
mapArguments<number>( ( x, y ): number => x + y, clbk, {}, 4 ); // $ExpectError
mapArguments( ( x, y ): number => x + y, clbk, {}, 4 ); // $ExpectError
}

0 comments on commit ce44167

Please sign in to comment.