Skip to content

Instantly share code, notes, and snippets.

@joelburton
Created February 24, 2024 00:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelburton/1ce686b0439d32cc3d2b17c30240a038 to your computer and use it in GitHub Desktop.
Save joelburton/1ce686b0439d32cc3d2b17c30240a038 to your computer and use it in GitHub Desktop.
Generics in TS
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
// TypeScript Generics 🧐
function choice(items) {
const item = items[Math.floor(Math.random() * items.length)];
console.log({ item });
return items[Math.floor(Math.random() * items.length)];
}
const rando1 = choice([1, 2, 3]);
const rando2 = choice(["a", "b", "c"]);
function choice_num(items: number[]): number {
const item = items[Math.floor(Math.random() * items.length)];
console.log({ item });
return items[Math.floor(Math.random() * items.length)];
}
const n = choice_num([1, 2, 3]);
function choice_str(items: string[]): string {
const item = items[Math.floor(Math.random() * items.length)];
console.log({ item });
return items[Math.floor(Math.random() * items.length)];
}
const s = choice_str(["a", "b", "c"]);
function choice_any(items: any[]): any {
const item = items[Math.floor(Math.random() * items.length)];
console.log({ item });
return items[Math.floor(Math.random() * items.length)];
}
const a = choice_any([1, 2, 3]);
const b = choice_any(["a", "b", "c"]);
function choice_union(items: (string | number)[]): (string | number) {
const item = items[Math.floor(Math.random() * items.length)];
console.log({ item });
return items[Math.floor(Math.random() * items.length)];
}
const c = choice_union([1, 2, 3]);
const d = choice_union(["a", "b", "c"]);
{
const c_num = choice_union([1, 2, 3]) as number;
}
function choice_generic<T>(items: T[]): T {
const item = items[Math.floor(Math.random() * items.length)];
console.log({ item });
return items[Math.floor(Math.random() * items.length)];
}
const e = choice_generic([1, 2, 3]);
const f = choice_generic(["a", "b", "c"]);
{
// explicit type not needed, but is ok to do:
const g = choice_generic<string>(["a", "b", "c"]);
}
class CartItem {
title: string;
price: number;
constructor(title: string, price: number) {
this.title = title;
this.price = price;
}
}
class Book extends CartItem { }
class Toy extends CartItem { }
class Cart<T> {
items: T[];
constructor(items: T[] = []) { this.items = items; }
count(): number { return this.items.length; }
}
const bookCart = new Cart([
new Book("Hamlet", 5),
new Book("The Bell Jar", 10)
]);
const count1 = bookCart.count();
{
const bookCart_explicit = new Cart<Book>();
bookCart_explicit.items.push(new Book("Regeneration", 12.50));
const count2 = bookCart_explicit.count();
}
class CartWithTotal<T> {
items: T[];
constructor(items: T[] = []) { this.items = items; }
count(): number { return this.items.length; }
totalCost(): number {
return this.items.reduce((prev, cur) => prev + cur.price, 0);
}
}
const numCart = new CartWithTotal([1, 2, 3, 4]);
const numCount = numCart.count();
const numTotal = numCart.totalCost(); // ut oh: "(cur as ShopItem).price"
class SafeCart<T extends CartItem> {
items: T[];
constructor(items: T[]) { this.items = items; }
count(): number { return this.items.length; }
totalCost(): number {
return this.items.reduce((prev, cur) => prev + cur.price, 0);
}
}
const ss = new SafeCart([new Book("Regeneration", 12.50)]);
const ns = new SafeCart([1, 2, 3]); // ERR
class AlsoSafeCart<T extends {price: number}> {
items: T[];
constructor(items: T[]) { this.items = items; }
count(): number { return this.items.length; }
totalCost(): number {
return this.items.reduce((prev, cur) => prev + cur.price, 0);
}
}
const catCart = new AlsoSafeCart([
{title: "Ezra, Viscount of Derp", price: 11.23, color: "creamsicle"},
{title: "Auden, Marquis of Meow", price: 99.95, color: "taupe-grey"},
]);
const appleCart = new AlsoSafeCart([ // ERR!
{title: "Fuji", color: "red"},
{title: "Gala", color: "red"},
]);
// Thank you for coming to my generic talk! 🐧
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment