Skip to content

Instantly share code, notes, and snippets.

@crutchcorn
Created December 4, 2018 03:28
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 crutchcorn/25086b340e0269cf0108f4c5f43084db to your computer and use it in GitHub Desktop.
Save crutchcorn/25086b340e0269cf0108f4c5f43084db to your computer and use it in GitHub Desktop.
Typescript generics rough intro
// So, let's say you have a function that you want to accept any function type and return that type
// Don't worry about why right away, just
function returnSelf(a: any): any {
return a;
}
returnSelf(2);
returnSelf('t');
const a = returnSelf('test').split(' ');
// The problem here is that with `any`, we're losing type info. We no longer know what the return value of `returnSelf` is
// How do we solve this? Type generics!
function returnSelfGeneric<T>(a: T): T {
return a;
}
returnSelfGeneric([123, 234]).map(() => {});
// Is the same thing as:
returnSelfGeneric<number[]>([123, 234]).map(() => { });
// The only reason we don't need the `<>` in the first example is because TS does a pretty good job at understanding what type you meant based on the args you're passing
// Ta-da! We're done. What we're saying here is that `a` should be any type. This type will be refered to as `T` from here on out. We can now use that same type
// elsewhere in the function definiton
// This is where you end up with things like `Promise<string>` comes into play. The defintion would look something like:
//Promise<T>((resolve: () => T, reject: () => any) => {then, catch});... You get the point, this is loose syntax and not valid
// What about multiple generics?
// Yup!
// We can restrict the TYPE of generic we want. This allows us to say that T can be any type so long as it extends on this object
function testGeneric<T extends {prop: number}, R>(arg1: T, arg2: R): T | R {
// Remember that comparisons can run on Dates and other stuff too
// What about something like this? We want a function that compares a prop but can have anything else? And `prop` should be a number? Seems complex, right?
if (arg1.prop > 2) {
return arg1;
} else {
return arg2;
}
}
// This is fine
testGeneric({ prop: 2, hello: 'hi' }, 23)
// This is not
testGeneric({ hello: 'hi' }, 23)
// You can even use type generics in other types
// & means that the type must have both. If T === {hello: string}, then AddType MUST have at least {prop: number, hello: string}
type AddType<T> = T & {prop: number}; // What does `&` do again?
// and finally with classes:
class GenericClass<T> {
prop: T;
constructor(arg1: T) {
this.prop = arg1;
}
method(): T {
return this.prop;
}
}
@crutchcorn
Copy link
Author

I have expanded this Gist into a much better laid out and expanded post:

https://unicorn-utterances.com/posts/typescript-type-generics/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment