Typescript quick reference
When I started writing TypeScript, I didnāt have much of any experience with strongly-typed languages. For that reason, it was a bit of a sharp learning curve. Especially, when I was used to JS that just lets you do whatever the heck you want.
Today, I really love TS and Iāve written a very basic intro that would have been helpful for me when I started. Hopefully, itās helpful to someone else out there.
Typing variables
This is generally pretty straightforward and easy to read:
// syntax is:
// const var_name: type = "value";
const thing: string = "asdf";
const otherThing: number = 3;
Note that these types are inline, meaning we set the type and declare the variable in the same line. You can also create the type then assign it to the variable, like this:
type Thing = string;
const thing: Thing = "asdf";
You wouldnāt probably do it this š way normally for a string, but when youāre making more complex types you certainly do. Letās look at typing objects.
Typing objects
Typing objects is also fairly easy. The only thing here to be conscious of is properties are required unless you append the ?
after the key. See aliases
in the example:
type User = {
name: string;
email: string;
score: number;
aliases?: string[]; // optional array of strings; can be `undefined`.
role: "reader" | "writer" | "admin"; // union
favoriteColor?: string; // optional
}
Since I mentioned it above, you could define this type inline, but it starts to get cumbersome:
const user: {
name: string;
email: string;
score: number;
aliases?: string[]; // optional array of strings; can be `undefined`.
role: "reader" | "writer" | "admin"; // union
favoriteColor?: string; // optional
} = {
name: "Pat",
email: "pat@hotmail.com",
score: 99,
role: "writer",
favoriteColor: "teal",
};
// ĀÆ\_(ć)_/ĀÆ
Typing functions
For some reason, this one was confusing to me initially. I think the reason it was confusing to me is that I was expecting there to be a type for a function. However, since all parts of the function should be typed (args and return value), to type a function itās just a matter of syntax. You will use (args) => return type
. Peep this:
// typing
type CapitalizeFunc = (text: string) => string;
// implementation
const capitalize: CapitalizeFunc = (text) => {
return text[0].toUpperCase() + text.slice(1);
}
// or do it inline
const capitalize2 = (text: string): string => text[0].toUpperCase() + text.slice(1);
Above we use constants that have a value set to an anonymous function. One benefit of doing this is that it prevents the function from being redefined later on. It comes with a set of asterisks, though. Iāll point you to a Google search for those.
If you prefer to write function() { ... }
style functions, you can do so, but you canāt create a type to represent the whole function in the same way (that I know ofā¦). You would do it like this:
function capitalize(text: string): string {
return text[0].toUpperCase() + text.slice(1);
}
Utility types
There are bunch of utility types built in to Typescript. These include types that make all properties of an object required, no properties required, select some properties of an object, etc. The syntax on these can be a little confusing at first (it was to me). Here are a few examples to gain your bearings:
// type with optional props
type Favorites = {
colors?: string[];
flavors?: string[];
numbers?: number[];
}
// now, a version with all required
// note that `Favorites` gets passed in to Required as an arg using the <...> syntax
type FavoritesReq = Required<Favorites>;
// fyi, š is the same as š
type FavoritesReq2 = {
colors: string[];
flavors: string[];
numbers: number[];
}
You can do the opposite of what the Required
type does with Partial
. So, like this:
// this gets us back to where we started with the Favorites type
type FavoritesOpt = Partial<FavoritesReq>;
The final example Iāll share is using the Pick
type. This gives us the ability to create a new type with some of the properties from another type. So, letās say we want favorites with only flavors
and numbers
:
type FavoritesLite = Pick<Favorites, "flavors" | "numbers">; // the second arg here is a union of the keys we want
Check out all the built-in utility types here: Typescript Utility Types. (If you just š lurve š these and want more utility types, check out type-fest š.)
Type Generics
This is sort of an advanced topic, but I think itās quite helpful to have some awareness of this early on. Typescript has āgenericsā which are types that receive an argument and use the type of the argument in the resulting type.
For our first example, letās say you have a function that wraps a value in an object, keeping the typing, and returns it (not necessarily a common use case, but itās easy for an example). We can maintain the typing using generics. Consider the following:
// Note how we precede the function args with the type args <...>(...) => ...
const wrapIt = <T>(incoming: T): { wrapped: T } => ({
wrapped: incoming,
});
The above example will let T
be any type. We can narrow what T
can be by extending existing types. Like this:
// T can only be a string, number, or boolean
const wrapIt = <T extends string | number | boolean>(incoming: T): { wrapped: T } => ({
wrapped: incoming,
});
// Or, to make things easier to read as the type maybe grows with more props
// we can break this out into a type then an implementation
type WrapperFunc = <T extends string | number | boolean>(incoming: T) => { wrapped: T };
const wrapIt: WrapperFunc = (incoming) => ({
wrapped: incoming,
});
Thereās a lot more to generics and things can get a lot more complex, but this at least gives some intro that can be helpful as youāre thinking of typing your projects.
Definitely, check out the Typescript docs on Generics for a lot more details.
Thatās it. Hope you like it.
Live, laugh, learn ā¤ļø.