Last active
June 30, 2023 19:51
-
-
Save ScriptRaccoon/c5667b85c5f4b9c7255b4a1daddc19ad to your computer and use it in GitHub Desktop.
Introduction to Generics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 1. Example: get last element of any array | |
| function last_element<X>(arr: Array<X>): X { | |
| return arr[arr.length - 1]; | |
| } | |
| // 2. Example: get id of an object which has an id | |
| type person = { | |
| name: string; | |
| age: number; | |
| id: string; | |
| }; | |
| type city = { | |
| name: string; | |
| location: string; | |
| id: string; | |
| }; | |
| function get_id<T extends { id: string }>(object: T): string { | |
| return object.id; | |
| } | |
| // 3. Example: add an id to an object | |
| function add_id<T>(obj: T): T & { id: string } { | |
| const id = crypto.randomUUID(); | |
| return { ...obj, id }; | |
| } | |
| // 4. Example: unify database entries | |
| type database_entry<X> = { | |
| id: string; | |
| created: Date; | |
| updated: Date; | |
| } & X; | |
| type user = database_entry<{ | |
| name: string; | |
| age: number; | |
| role: "admin" | "editor" | "guest"; | |
| }>; | |
| type post = database_entry<{ | |
| title: string; | |
| text: string; | |
| likes: number; | |
| }>; | |
| // 5. Example: utilities | |
| function is_equal<X>(a: X, b: X) { | |
| return a === b; | |
| } | |
| function identity<X>(a: X): X { | |
| return a; | |
| } | |
| function compose<X, Y, Z>( | |
| f: (x: X) => Y, | |
| g: (y: Y) => Z | |
| ): (x: X) => Z { | |
| return function (x: X): Z { | |
| const y = f(x); | |
| const z = g(y); | |
| return z; | |
| }; | |
| } | |
| // 6. Example: Promises | |
| async function get_answer(): Promise<number> { | |
| return 42; | |
| } | |
| async function get_user(): Promise<user> { | |
| return { | |
| id: "u591y", | |
| created: new Date("2023-04-02"), | |
| updated: new Date("2023-05-26"), | |
| name: "John Doe", | |
| age: 21, | |
| role: "editor", | |
| }; | |
| } | |
| // 7. Example: cache decorator function | |
| async function expensive_api_call(): Promise<string> { | |
| return "This is the result"; | |
| } | |
| function cache_function<T>(fun: () => T, duration: number): () => T { | |
| let cache: T; | |
| let saved: Date; | |
| return function () { | |
| const now = new Date(); | |
| if (cache && now.getTime() - saved.getTime() < duration) { | |
| console.log("read from cache ๐"); | |
| return cache; | |
| } else { | |
| console.log("need to compute ๐"); | |
| const result = fun(); | |
| cache = result; | |
| saved = new Date(); | |
| return result; | |
| } | |
| }; | |
| } | |
| const cached_api_call = cache_function(expensive_api_call, 10000); | |
| setInterval(async () => { | |
| await cached_api_call(); | |
| }, 1000); | |
| // 8. Example: Generic classes | |
| // See the Server class in | |
| // https://github.com/ScriptRaccoon/svelte-chat-app/blob/main/server.ts | |
| // 9. Example: Function evaluation and currying | |
| function evaluate<X, Y>(fun: (x: X) => Y, x: X): Y { | |
| return fun(x); | |
| } | |
| function curry<X, Y, Z>( | |
| fun: ([x, y]: [X, Y]) => Z | |
| ): (x: X) => (y: Y) => Z { | |
| return (x: X) => (y: Y) => fun([x, y]); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment