Skip to content

Instantly share code, notes, and snippets.

@bryandidur
Created February 15, 2020 00:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bryandidur/50846ede8b725df5c9a85e31f8018710 to your computer and use it in GitHub Desktop.
Save bryandidur/50846ede8b725df5c9a85e31f8018710 to your computer and use it in GitHub Desktop.
Examples of Typescript Generics
/*
|-----------------------------------------------------
| Example 1: basic use of generics
|-----------------------------------------------------
| 'T' represents a dinamyc type passed to the function
|
*/
// function identity<T>(arg: T): T {
//   return arg;
// }
// // 'number' is being passed as the dinamyc type 'T'
// console.log({ result: identity<number>(10) });
// // omitting type declaration will instruct compiler to automatically set the type as being the argument's data type
// console.log({ result: identity(10) }); // computed type: 'number'
// console.log({ result: identity('string as dinamyc type') }); // computed type: 'string'

/*
|-----------------------------------------------------
| Example 2: compile error
|-----------------------------------------------------
*/
// Cannot ensure access to the '.length', since it can be 'any'.
// function identity<T>(arg: T): T {
//   console.log({ length: arg.length });

//   return arg;
// }

/*
|-----------------------------------------------------
| Example 3: ensure 'T' to an array of dinamyc types, so we can access '.length'
|-----------------------------------------------------
*/
// function identity<T>(arg: T[]): T[] {
//   console.log({ length: arg.length });

//   return arg;
// }
// console.log({ result: identity(['string as dinamyc type']) });

/*
|-----------------------------------------------------
| Example 4: multiple dinamyc types
|-----------------------------------------------------
*/
// function doSomething<U>(arg: U): U {
//   return arg;
// }

// function identity<T, R>(arg1: T, arg2: R): R {
//   doSomething<T>(arg1);
//   // doSomething<R>(arg1); // compile error: Argument of type 'T' is not assignable to parameter of type 'R'

//   return arg2;
// }
// console.log({ result: identity<number, string>(10, 'abc') });
// // console.log({ result: identity(10, 'abc') }); // computed types: 'number', string'

/*
|-----------------------------------------------------
| Example 5: generic interfaces
|-----------------------------------------------------
*/
function identity<T>(arg: T): T {
  return arg;
}

/*--- using 'in-place' interface expressions ---*/
// const myIdentity: <U>(arg: U) => U = identity; // '<U>(arg: U) => U' expression defines the expected generic function interface
// console.log({ result: myIdentity<number>(10) });

// const myIdentity: {<U>(arg: U): U} = identity; // same as above, but using the interface expression as an object/interface syntax
// console.log({ result: myIdentity<number>(10) });

/*--- using literal/explicit interface expressions ---*/
// interface GenericIdentityFn {
//   <T>(arg: T): T;
// }
// const myIdentity: GenericIdentityFn = identity;
// console.log({ result: myIdentity<number>(10) });

/*--- using literal/explicit interface expressions again, but defining the generic type to be available in whole interface ---*/
interface GenericIdentityFn<T> {
  (arg: T): T;
  // we can continue using the 'T' generic as many times as we want below
}
const myIdentity: GenericIdentityFn<number> = identity;
console.log({ result: myIdentity(10) });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment