Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created June 7, 2017 12:10
Show Gist options
  • Save bennadel/523b5475d0ab6e797d4e5df87bff8b49 to your computer and use it in GitHub Desktop.
Save bennadel/523b5475d0ab6e797d4e5df87bff8b49 to your computer and use it in GitHub Desktop.
Using Type Argument Inference When Accepting Generic Callbacks In TypeScript And Node.js
// I define the callback function interface for the .map() method. This entire interface
// is parameterized with the given Type <T> so that we can facilitate "type argument
// inference" in the method signature for .map().
interface TokensMapCallback<T> {
( token: string ) : T;
}
class Tokens {
private _tokens: string[];
// I initialize the tokens class with the given tokens.
constructor( tokens: string[] ) {
this._tokens = tokens;
}
// ---
// PUBLIC METHODS.
// ---
// I map the internal tokens using the given callback.
// --
// NOTE: By using <T> to parameterize both the method and the callback type, we
// allow for "type argument inference", which is when TypeScript looks at the method
// argument and uses its Type as way to automatically determine which type should be
// used to parameterize the map<T> method. In this case, it will look at the return-
// type of the callback as the parameterization type (as defined in TokensMapCallback).
public map<T>( callback: TokensMapCallback<T> ) : T[] {
return( this._tokens.map( callback ) );
}
// I map the internal tokens using the given callback.
// --
// NOTE: This has the same effect as the previous map<T> method, except for this uses
// an in-line type definition for the callback. You can still see that the callback
// is defined to return T, which can then allow for "type argument inference" for the
// parameterization of .map2<T>.
public map2<T>( callback: ( token: string ) => T ) : T[] {
return( this._tokens.map( callback ) );
}
}
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
var tokens = new Tokens( [ "Sarah", "Joanna", "Tricia" ] );
// Let's map the tokens using a Callback that returns a String value.
// --
// NOTE: The :string return type of the callback will be used to infer the return
// type of the .map() method.
var greetings: string[] = tokens.map(
( token: string ) : string => {
return( `Hello, ${ token }.` );
}
);
for ( var greeting of greetings ) {
console.log( greeting );
}
// Let's map the tokens using a Callback that returns a Boolean value.
// --
// NOTE: The :boolean return type of the callback will be used to infer the return
// type of the .map2() method.
var checks: boolean[] = tokens.map2(
( token: string ) : boolean => {
return( token === "Joanna" );
}
);
for ( var check of checks ) {
console.log( check );
}
public map<T>( callback: CallbackFunction ) : T[] { /* ... */ }
var results = instance.map<string>( /* callback */ );
public map<T>( callback: CallbackFunction<T> ) : T[] { /* ... */ }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment