Skip to content

Instantly share code, notes, and snippets.

@jarhoads
Created June 4, 2019 19:20
Show Gist options
  • Save jarhoads/a86de35c31b89f768a2b3b19a058369c to your computer and use it in GitHub Desktop.
Save jarhoads/a86de35c31b89f768a2b3b19a058369c to your computer and use it in GitHub Desktop.
typescript functions
function getAverage(a: number, b: number, c: number): string {
const total = a + b + c;
const average = total / 3;
return `The average is: ${average}`;
}
const result = getAverage(4, 3, 8);
console.log(result);
// uses optional parameter c
function getAverageOpt(a: number, b: number, c?: number) {
let total = a + b;
let count = 2;
if(typeof c !== 'undefined') {
total += c;
count++;
}
// const total = a + b + c;
const average = total / count;
return `The average is: ${average}`;
}
const result2 = getAverageOpt(4, 3);
console.log(result2);
// default parameters - should consider default params when using optional params
function concatenate(items: string[], separator = ',', beginAt = 0, endAt = items.length): string {
let result = '';
for(let i=beginAt; i<endAt; i++){
result += items[i];
if(i < (endAt-1)){ result += separator; }
}
return result;
}
const items = ['A','B','C'];
const allItems = concatenate(items);
const partialHyphen = concatenate(items, '-', 1);
console.log(`Concatenated all: ${allItems}, Partial with hyphens: ${partialHyphen}`);
// rest parameters
function getAverageMany(...a: number[]): string {
let total = 0;
let count = 0;
for(let i=0; i<a.length; i++){
total += a[i];
count++;
}
const average = total / count;
return `The average is: ${average}`;
}
const resultMany = getAverageMany(2, 4, 6, 8, 10);
console.log(resultMany);
// function overloads
// the implementation signature cannot be called directly, so all calls must be compatible with one of the overloads
function getAverageOverload(a: string, b: string, c: string): string;
function getAverageOverload(a: number, b: number, c: number): string;
// implementation signature
function getAverageOverload(a: any, b: any, c: any): string {
const total = parseInt(a, 10) + parseInt(b, 10) + parseInt(c, 10);
const average = total / 3;
return 'The average is ' + average;
}
// The average is 5
const resultOverload = getAverageOverload(4, 3, 8);
console.log(resultOverload);
// special overloads - matching string constants
// There must be at least one nonspecialized signature.
// Each specialized signature must return a subtype of a nonspecialized signature.
// The implementation signature must be compatible with all signatures.
// The most common case for specialized signatures is that the nonspecialized signature returns a superclass,
// with each overload returning a more specialized subclass that inherits (or is structurally compatible with) the superclass
// class HandlerFactory {
// getHandler(type: 'Random'): RandomHandler;
// getHandler(type: 'Reversed'): ReversedHandler;
// getHandler(type: string): Handler; // non-specialized signature
// getHandler(type: string): Handler { // implementation signature
// switch (type) {
// case 'Random':
// return new RandomHandler();
// case 'Reversed':
// return new ReversedHandler();
// default:
// return new Handler();
// }
// }
// }
// arrow functions - leave out function keyword, use =>
const shortAddNumbers = (a: number, b: number) => a + b;
const mediumAddNumbers = (a: number, b: number) => {
return a + b;
}
const longAddNumbers = function (a: number, b: number) {
return a + b;
}
// surround returned objects with ()
const makeName = (f: string, l: string) => ({ first: f, last: l });
// can use to preserve 'this'
// The scope of this is lost when the function is invoked by the timer,
// so the value of this.text is undefined, as we are no longer in the object context
// const scopeLosingExample = {
// text: "Property from lexical scope",
// run: function () {
// setTimeout(function () {
// console.log(this.text);
// }, 1000);
// }
// };
// alerts undefined
// scopeLosingExample.run();
// the arrow syntax fixes the scope problem and
// allows the correct value to be obtained
const scopePreservingExample = {
text: "Property from lexical scope",
run: function () {
setTimeout(() => {
console.log(this.text);
}, 1000);
}
};
// alerts "Property from lexical scope"
scopePreservingExample.run();
// currying
// Currying is a process whereby a function with multiple parameters is
// decomposed into multiple functions that each take a single parameter
// The resulting chain of functions can be called in stages,
// with the partly applied stage becoming a reusable implementation of the combined function and value
const multiply = (a: number) => (b: number) => a * b;
// Pass both arguments in sequence: 30
const numA = multiply(5)(6);
// Pass just the first argument and re-use
const orderOfMagnitude = multiply(10);
// 10
const deca = orderOfMagnitude(1);
// 100
const hecta = orderOfMagnitude(deca);
// 1,000
const kilo = orderOfMagnitude(hecta);
// can also curry with overloads
function multiplyOverload(a: number): (b: number) => number;
function multiplyOverload(a: number, b: number): number;
function multiplyOverload(a: number, b: number = 0) {
if (b === null || b === 0) {
return (b: number) => a * b;
}
return a * b;
}
// Pass both arguments "normally": 30
const numAOverload = multiplyOverload(5, 6);
// Pass just the first argument and re-use
const orderOfMagnitudeOverload = multiplyOverload(10);
// 10
const decaOverload = orderOfMagnitudeOverload(1);
// 100
const hectaOverload = orderOfMagnitude(deca);
// 1,000
const kiloOverload = orderOfMagnitude(hecta);
// logging example
const log = (source: string) => (message: string) => console.log(source, message);
const customLog = log('Custom Log:');
// Custom Log: Message One
customLog('Message One');
// Custom Log: Message Two
customLog('Message Two');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment