# Series: TypeScript - Tips & Tricks (21 Parts) — Luca Del Puppo > Complete 21-part technical series "TypeScript - Tips & Tricks" by Luca Del Puppo (https://delpuppo.net/blog/series/ts-tips-and-tricks/). Ordered chronologically from Part 1 to Part 21. - **Canonical Series URL**: https://delpuppo.net/blog/series/ts-tips-and-tricks/ - **Hashnode Series Mirror**: https://blog.delpuppo.net/series/ts-tips-and-tricks - **Blog Index LLMs.txt**: https://delpuppo.net/blog/llms.txt ## Series Curriculum 1. [Part 1: Typescript - Tips & Tricks - typeof](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-typeof/) (Feb 15, 2021) — Today I want to start a series of tips and tricks about Typescript. I will try to publish two/three... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-typeof/llms.txt)) 2. [Part 2: Typescript - Tips & Tricks - Literal Types](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-literal-types/) (Feb 17, 2021) — Welcome back! Today I show you the Literal Types. This feature permits you to create a set of... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-literal-types/llms.txt)) 3. [Part 3: Typescript - Tips & Tricks - keyof](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-keyof/) (Feb 19, 2021) — Welcome back! Today I'll talk about the keyof operator. This operator helps us to extract the... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-keyof/llms.txt)) 4. [Part 4: Typescript - Tips & Tricks - Union and Intersection](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-union-and-intersection/) (Feb 22, 2021) — Hi and welcome back! Today I talk about Union and Intersection. In some cases, we have to combine... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-union-and-intersection/llms.txt)) 5. [Part 5: Typescript - Tips & Tricks - Overloaded Functions](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-overloaded-functions/) (Feb 24, 2021) — Welcome back, guys! The topic of today is Overloaded Functions. All self-respecting programming... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-overloaded-functions/llms.txt)) 6. [Part 6: Typescript - Tips & Tricks - this parameter](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-this-parameter/) (Feb 26, 2021) — Hello everybody and welcome back, today I'll talk about this parameter. Sometimes we need to create... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-this-parameter/llms.txt)) 7. [Part 7: Typescript - Tips & Tricks - any vs. unknown](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-any-vs-unknown/) (Mar 1, 2021) — Hi guys, today I'll talk about the difference between any and unknown. Any Any type is a particular... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-any-vs-unknown/llms.txt)) 8. [Part 8: Typescript - Tips & Tricks - Optional modifier](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-optional-modifier/) (Mar 3, 2021) — Hi guys and welcome back, Today I'll talk about the optional modifier. Sometimes we have objects that... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-optional-modifier/llms.txt)) 9. [Part 9: Typescript - Tips & Tricks - Index Signature](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-index-signature/) (Mar 5, 2021) — Welcome back guys, today I'll speak about the "Index Signature". In some cases, we need to create... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-index-signature/llms.txt)) 10. [Part 10: Typescript - Tips & Tricks - readonly modifier](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-modifier/) (Mar 8, 2021) — How many times we expect an object property to have a value but it isn't? In these cases,... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-modifier/llms.txt)) 11. [Part 11: Typescript - Tips & Tricks - Readonly Array](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-array/) (Mar 10, 2021) — function sortAndReverse(list: number[]): number[] { return list.sort().reverse(); } const list =... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-array/llms.txt)) 12. [Part 12: Typescript - Tips & Tricks - Tuple](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-tuple/) (Mar 12, 2021) — Tuple types allow you to express an array with a fixed number of elements whose types are known, but... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-tuple/llms.txt)) 13. [Part 13: Typescript - Tips & Tricks - Non-null assertion operator](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-non-null-assertion-operator/) (Mar 15, 2021) — In some cases, you have a field that you initialize in a method, and if you follow the flow of the... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-non-null-assertion-operator/llms.txt)) 14. [Part 14: Typescript - Tips & Tricks - Never type](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-never-type/) (Mar 17, 2021) — Today I want to talk about the never type. As you can understand, this type identifies a piece of... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-never-type/llms.txt)) 15. [Part 15: Typescript - Tips & Tricks - Assert Function](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-assert-function/) (Mar 19, 2021) — There are times that we need to create some assertions to be sure an object respects some rules. A... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-assert-function/llms.txt)) 16. [Part 16: Typescript - Tips & Tricks - Type Guard](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-type-guard/) (Mar 22, 2021) — There are some cases, where we need to detect the type of the object to get the correct... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-type-guard/llms.txt)) 17. [Part 17: Typescript - Tips & Tricks - Conditional Type](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-conditional-type/) (Mar 24, 2021) — In some cases, we need to detect if an object/type has specific properties or characteristics. Let me... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-conditional-type/llms.txt)) 18. [Part 18: Typescript - Tips & Tricks - infer keyword](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-infer-keyword/) (Mar 26, 2021) — Today I talk about the infer keyword. Sometimes, we need to get the value type of an array or get the... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-infer-keyword/llms.txt)) 19. [Part 19: Typescript - Tips & Tricks - Mapped Types](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-mapped-types/) (Mar 29, 2021) — In some cases, we need to manipulate some types to create new types. In these cases, we have to use... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-mapped-types/llms.txt)) 20. [Part 20: Typescript - Tips & Tricks - Advanced Types](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-advanced-types/) (Mar 31, 2021) — Hi Guys, Today I'll show you some advanced utilities exposed by the typescript language. Let's... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-advanced-types/llms.txt)) 21. [Part 21: Typescript - Tips & Tricks - Rest Parameters & Rest Arguments](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-rest-parameters-rest-arguments/) (Apr 2, 2021) — Hi guy and welcome back :) Today I'll talk about the Rest Parameters and the Rest... ([Article LLMs.txt](https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-rest-parameters-rest-arguments/llms.txt)) --- ## Full Series Content ### Part 1 of 21: Typescript - Tips & Tricks - typeof - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-typeof/ - **Published**: Feb 15, 2021 - **Tags**: typescript, webdev Today I want to start a series of tips and tricks about Typescript. I will try to publish two/three tips & tricks a week. Before start, I want to explain why I start this series. I start this series because every day I see too many _any_ types in the typescript files and so I want to help the developers to learn better the typescript language. ## typeof Today I start with the **typeof** operator. Typeof is an operator used to detect the type of our variables. A little preamble, typeof is also a javascript operator, but with typescript, it has superpowers. Typeof in javascript has these behaviors: ```ts const valueString = "string"; const valueNumber = 1; const valueBoolean = true; const valueBigInt = 1n; const valueFunction = () => true; const valueUndefined = undefined; const valueNull = null; const object = { prop1: "value1", prop2: "value2", }; console.log(typeof valueString); // string console.log(typeof valueNumber); // number console.log(typeof valueBoolean); // boolean console.log(typeof valueBigInt); // bigint console.log(typeof valueFunction); // function console.log(typeof valueUndefined); // undefined console.log(typeof valueNull); // object console.log(typeof object); // object ``` How we can see some things are strange: e.g. when we get the typeof of a null variable javascript returns an object type. But here we see the same example in typescript: ```ts type valueStringType = typeof valueString; // "string" type valueNumberType = typeof valueNumber; // 1 type valueBooleanType = typeof valueBoolean; // true type valueBigIntType = typeof valueBigInt; // 1n type valueFunctionType = typeof valueFunction; // () => boolean type valueUndefinedType = typeof valueUndefined; // undefined type valueNullType = typeof valueNull; // null type objectType = typeof object; // { prop1: string; prop2: string; } ``` The first impact is friendlier for us developers because the typeof operator converts the type exactly as expected. The best advantages can be seen in the types: function, null, object. But now an advanced example: ```ts const item = { id: '0000', name: 'Item', unit: { id: '1', code: 'PZ' }, variants: [{ id: '1', code: '001', color: 'FFFFFF' }] }; type Item = typeof item; type Unit = typeof item["unit"]; type Variant = typeof item.variants[number]; ``` In this example, we can see how we can extract simple types from a complex object. I leave you the [in this reference](https://www.typescriptlang.org/docs/handbook/2/typeof-types.html) of the official documentation of this operator. For today is all. See you soon! --- ### Part 2 of 21: Typescript - Tips & Tricks - Literal Types - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-literal-types/ - **Published**: Feb 17, 2021 - **Tags**: typescript, webdev Welcome back! Today I show you the [Literal Types](https://www.typescriptlang.org/docs/handbook/literal-types.html). This feature permits you to create a set of relationship values. ```ts type Direction = "North" | "South" | "East" | "West"; ``` Literal types in this case create also a Type Guard of your field, so the compiler can detect your errors or your typos. ```ts let directionError: Direction = "east" // Type '"east"' is not assignable to type 'Direction' let direction: Direction = "East" // OK ``` You can create Literal Types from different types such as booleans, numbers, and strings, and you can combine together different types too. ```ts type Valid = false | 0 | true | 1; ``` That's all for today See you soon guys! --- ### Part 3 of 21: Typescript - Tips & Tricks - keyof - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-keyof/ - **Published**: Feb 19, 2021 - **Tags**: typescript, webdev Welcome back! Today I'll talk about the **keyof** operator. This operator helps us to extract the object's properties such as [Literal-types](https://dev.to/puppo/typescript-tips-tricks-literal-types-10md) ```ts type Person = { firstName: string; surName: string; age: number; location: string; }; type PersonKeys = keyof Person; // "firstName" | "surName" | "age" | "location" ``` This operator can help us to create new methods that should depend of other types; e.g. ```ts function get(obj: T, prop: K): T[K] { return obj[prop]; } function set(obj: T, prop: K, value: T[K]): void { obj[prop] = value; } ``` but also to create new types from other types e.g ```ts type ReadOnly = { readonly [K in keyof T]: T[K]; }; type ReadOnlyPerson = ReadOnly /* type ReadOnlyPerson = { readonly firstName: string; readonly surName: string; readonly age: number; readonly location: string; } */ ``` How we can see this operator is more powerful and it can help us to create new strict type or new strict methods. That's all for today. See you soon guys! --- ### Part 4 of 21: Typescript - Tips & Tricks - Union and Intersection - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-union-and-intersection/ - **Published**: Feb 22, 2021 - **Tags**: typescript, webdev Hi and welcome back! Today I talk about [Union and Intersection](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html). In some cases, we have to combine different types to create new types, or sometimes we have parameters that could be of different types. Typescript helps us with two powerful features: _Union_(|) and _Intersection_(&). ## Union A union type describes a value that can be one of several types. ```ts type Padding = number | string let paddingNumber: Padding = 1 let paddingString: Padding = '----'; let paddingError: Padding = true // Type 'boolean' is not assignable to type 'Padding'. ``` In this case, the padding can be a number or a string, and the compiler detects if you set different types; this feature can be used also with custom types. ```ts type Fish = { name(): string; swim(): true; }; type Cat = { name(): string; meows(): true; }; type Pet = Fish | Cat; // { name(): string; } declare function createPet(): Pet; let pet = createPet(); pet.name() pet.swim() // Property 'swim' does not exist on type 'Pet' pet.meows(); // Property 'meows' does not exist on type 'Pet' ``` In this example we can see how the union type creates the Pet type; the Pet type is composed by a single method "name". This method is the only one present in the two initial types: Fish and Cat. ## Intersection An intersection type combines multiple types into one. ```ts type Point2D = { x: number; y: number; }; type Point3D = Point2D & { z: number; }; let point2d: Point2D = { x: 0, y: 0 }; let point3d: Point3D = { x: 0, y: 0, z: 0 }; ``` We can see that the Point3D type is the union of the Type Point2D and the type { z: number; }. That's all for today! See you soon guys! --- ### Part 5 of 21: Typescript - Tips & Tricks - Overloaded Functions - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-overloaded-functions/ - **Published**: Feb 24, 2021 - **Tags**: typescript, webdev Welcome back, guys! The topic of today is [Overloaded Functions](https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#overloaded-functions). All self-respecting programming languages ​​have overloaded functions, so typescript has this feature too. To use this feature in typescript, we have to declare all the signatures of this function, and at the end, we have to write a single function that includes all these signatures. The last function is the only one with the implementation. The peculiarity of this function is that it must include all the possible implementations of the previous signatures. Here's a simple example that is more exhaustive than all these words. ```ts function reverse(value: string): string; function reverse(value: string[]): string[]; function reverse(value: string | string[]): string | string[] { if (typeof value === "string") return value.split("").reverse().join(""); return value.slice().reverse(); } console.log(reverse("Tips")); // 'spiT' console.log(reverse(["T", "i", "p", "s"])); // [ 's', 'p', 'i', 'T' ] ``` As we can see, there are 2 signatures of the "reverse" function, one gets a string and returns a string as result, the second one gets a string array and returns a string array as result. The third function is the real implementation of this function. As we can see the parameter type is a literal-type that includes a string or a string array (the combination of the type in the signatures' parameters), we can make the same considerations for the result's type. In the function implementations, we detect the parameter's type at runtime and manipulate the parameter to return the correct type according to the function we are overloading. An important thing to remember is that the implementation function is not exposed. That's all for today! See you soon guys! --- ### Part 6 of 21: Typescript - Tips & Tricks - this parameter - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-this-parameter/ - **Published**: Feb 26, 2021 - **Tags**: typescript, webdev Hello everybody and welcome back, today I'll talk about [this parameter](https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters). Sometimes we need to create functions that have to know the context to run correctly. A simple example, the mathematical power must know the base and the exponent number to run correctly. So we could create a simple method like this: ```ts function pow(exponent: number) { return Math.pow(this.number, exponent); } const basePow = { base: 2, pow, }; console.log(basePow.pow(2)); ``` If we build and run this code, the console log's result will be "NaN", because in the pow method the value of the field "this.number" is undefined. _N.B. if you build this code with the strict mode on true, the compiler detects the problem at build time and so the build fails_ But now I explain the solution. In this case, the problem is the "number" field that doesn't exist in this context. Typescript helps us to prevent this error, it allows us to indicate the "this" type as a parameter. To do this, we need to declare the "this" context as the first parameter of the function, so typescript detects the "this" type and it helps us to prevent errors and bugs. So the code in the previous example should be rewritten like this: ```ts function pow(this: { base: number }, exponent: number) { return Math.pow(this.base, exponent); } const basePow = { base: 2, pow, }; console.log(basePow.pow(2)); ``` In this case, the result at runtime is "4" as expected. If by chance we write the "basePow" object like this: ```ts const basePow = { value: 2, pow, }; ``` when we try to call the method "basePow.pow(2)", the typescript language detects the error, and in this case, when we try to build the code the build fails. That's all! See you soon guys! --- ### Part 7 of 21: Typescript - Tips & Tricks - any vs. unknown - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-any-vs-unknown/ - **Published**: Mar 1, 2021 - **Tags**: typescript, webdev Hi guys, today I'll talk about the difference between _any_ and _unknown_. **Any** Any type is a particular type in typescript. If you use this type, the compiler doesn't check your code, and the power is in your hands, but from great powers comes great responsibilities. In this case, the compiler doesn't check your code, but maybe your code could have bugs; these bugs will most likely be found by a user during his operations. **Unknown** Unknown type is another particular type in typescript, it's similar to _Any_ type but it helps us to prevent bugs at build time. The unknown type helps us to force the check of its type before using it. Now let's turn to some examples. _Any Type_ ```ts let myAny: any = true myAny.trim().reverse().split(','); let myAnyNumeric: number = myAny; const sum = myAnyNumeric + 3; ``` In this case, we can see a problem right away; in the second line, we try to call the trim method on a boolean type. This code at runtime throws an exception, but we need to run this code to detect this bug. In the third line instead, I set a boolean type to a numeric type, and in the next line, I add three to this value. Ok, I think you have understood the possible problems you could have if you overuse any type. _Unkown Type_ ```ts let myUnknown: unknown = true; myUnknown.trim(); // Property 'trim' does not exist on type 'unknown'.ts(2339) let myAnyNumeric: number = myUnknown; // Type 'unknown' is not assignable to type 'number'.ts(2322) if (typeof myUnknown === 'string') myUnknown.trim(); if (typeof myUnknown === "number") { let myAnyNumeric: number = myUnknown; const sum = myAnyNumeric + 3; } ``` In this example, we can see the power of using unknown type instead of any type. This type doesn't stop the compiler check but it helps us to check our type to prevent bugs at runtime. Typescript understands what you want to do, and it indicates you the correct way to prevent bugs. After this post, I think that from now on you will prefer to use _unknown_ instead of _any_ and I know the reason ;) That's all! Bye-bye guy!! --- ### Part 8 of 21: Typescript - Tips & Tricks - Optional modifier - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-optional-modifier/ - **Published**: Mar 3, 2021 - **Tags**: typescript, webdev Hi guys and welcome back, Today I'll talk about the optional modifier. Sometimes we have objects that have some optional properties. In these cases, we need to identify the optional and the required properties, so the consumers can know what is required and what not. To do this in typescript we have a special modifier named "optional" and it is identified by a question mark (_?_). Let's see an example: ```ts export type Person = { name: string; surname: string; email: string; phone?: string; }; const person1: Person = { name: "name1", surname: "surname1", email: "email1@email1.it", }; const person2: Person = { name: "name2", surname: "surname2", email: "email2@email2.it", phone: "123", }; ``` In this example we can see the optional modifier in action, the "phone" property is marked as optional so in the "person1" object we can avoid setting the "phone" property. This modifier, also, could be used in the functions' parameters if we have one or more optional parameters. A simple example. ```ts function printPerson(name: string, email: string, phone?: string): void { console.log(`Name: ${name}`); console.log(`Email: ${email}`); if (phone) console.log(`Phone: ${phone}`); } printPerson("name1", "email1@email1.it"); /* Name: name1 Email: email1@email1.it */ printPerson("name2", "email2@email1.it", "123"); /* Name: name2 Email: email2@email1.it Phone: 123 */ ``` We can see how in the first example we can avoid setting the phone parameter because it's optional. From the optional modifier, it's all. See you soon guy! --- ### Part 9 of 21: Typescript - Tips & Tricks - Index Signature - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-index-signature/ - **Published**: Mar 5, 2021 - **Tags**: typescript, webdev Welcome back guys, today I'll speak about the _"Index Signature"_. In some cases, we need to create some special types like dictionaries. These special types have some keys that identifies the elements and the datas. A simple example: ```ts export type User = { name: string, email: string; session: string } export type UserDictionary = { [username: string]: User } const userDictionary: UserDictionary = { 'myusername': { email: "myemail@email.it", name: "myname", session: "session" }, 'myusername1': { email: "myemail1@email.it", name: "myname1", session: "session", }, }; console.log(userDictionary.myusername); // { email: 'myemail@email.it', name: 'myname', session: 'session' } console.log(userDictionary["myusername"]); // { email: 'myemail@email.it', name: 'myname', session: 'session' } console.log(userDictionary.myusername1); // { email: 'myemail1@email.it', name: 'myname1', session: 'session' } console.log(userDictionary["myusername1"]); // { email: 'myemail1@email.it', name: 'myname1', session: 'session' } delete userDictionary.myusername; ``` In this case, the _UserDictionary_ is a special type where the usernames are the keys of the objects and the user data are the values. This type is powerful because it permits the consumer to access directly to the data if it knows the keys and it permits to store a unique value of a specific key. With the index signature, we can create special types where the keys can be string or number. An important thing that you must remember is that the keys of these objects can be iterated with the for-in loop or with the Object.keys method. ```ts console.log(Object.keys(userDictionary)); // [ 'myusername', 'myusername1' ] for (const key in userDictionary) { console.log(key); } /* 'myusername' 'myusername1' */ ``` It's all from the _Index Signature_ for today. Bye-bye guys! --- ### Part 10 of 21: Typescript - Tips & Tricks - readonly modifier - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-modifier/ - **Published**: Mar 8, 2021 - **Tags**: typescript, webdev How many times we expect an object property to have a value but it isn't? ![Magic gif](https://media.giphy.com/media/3o7TKP9ln2Dr6ze6f6/source.gif) In these cases, unfortunately, we spend a lot of time searching for who changes the value of this property. Today I want to show you a special modifier that helps you to prevent this problem and preserve your time. This modifier is the [readonly](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#readonly-and-const). The readonly modifier helps you to prevent someone can change your property, so, the object's property can set only in the object initialization. A simple example ```ts type Point = { x: number; y: number; }; const point: Point = { x: 10, y: 10, }; point.x = 20; point.y = 20; type ReadOnlyPoint = { readonly x: number; readonly y: number; }; const readOnlyPoint: ReadOnlyPoint = { x: 10, y: 10, }; readOnlyPoint.x = 20; // Cannot assign to 'x' because it is a read-only property readOnlyPoint.y = 20; // Cannot assign to 'y' because it is a read-only property ``` In this example you can see how in the first case you can change the value of the properties 'x' and 'y'; on the contrary, in the second case, you can't change the properties because they are marked as readonly. As you can see, the readonly modifier can prevent the change of the values of the properties and save your code from annoying bugs. Typescript also exposes a special type to convert your types to full readonly types; this type is called _ReadOnly_. So we can review the previous example in this way ```ts type Point = { x: number; y: number; }; const point: Point = { x: 10, y: 10, }; point.x = 10; const readOnlyPoint: ReadOnly = { x: 10, y: 10, }; readOnlyPoint.x = 10; // Cannot assign to 'x' because it is a read-only property readOnlyPoint.y = 20; // Cannot assign to 'y' because it is a read-only property ``` From the readonly modifier, it's all! Goodbye guys! --- ### Part 11 of 21: Typescript - Tips & Tricks - Readonly Array - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-array/ - **Published**: Mar 10, 2021 - **Tags**: typescript, webdev ```ts function sortAndReverse(list: number[]): number[] { return list.sort().reverse(); } const list = [1, 4, 5, 2]; sortAndReverse(list); console.log(list); ``` What's the result of the final console log? 1. [ 1, 4, 5, 2 ] 2. [ 5, 4, 2, 1 ] 3. [ 2, 5, 4, 1 ] Unfortunately, the correct answer is the second one. ![Unfortunately](https://media.giphy.com/media/XHwN2ViWQR6vmBoRdd/source.gif) In this stupid example, you can see how some array methods can have some side effects. The sort and the reverse methods return a new array with the result but also they change the initial array. Typescript can help us to prevent these side effects using read-only arrays. The read-only arrays identify the methods that modify the initial array and raise an error when you call these methods. But now, how can you use the read-only array? It's easy guys, you need to indicate the readonly modifier before the type of your array. So, the previous example can change in this way ```ts function sortAndReverse(list: readonly number[]): number[] { return list.slice().sort().reverse(); } const list = [1, 4, 5, 2]; sortAndReverse(list); console.log(list); ``` In this case, the _sortAndReverse_ method returns as result "[ 5, 4, 2, 1 ]" like in the first example, but more important is that the final console log returns "[ 1, 4, 5, 2 ]", the initial value of the "list" array. If in this case, you try to remove the "slice" method, you can see how typescript indicates an error (Property 'sort' does not exist on type 'readonly number[]'), and it helps you to prevent strange side effects. It's all for today! Bye Bye Guys! --- ### Part 12 of 21: Typescript - Tips & Tricks - Tuple - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-tuple/ - **Published**: Mar 12, 2021 - **Tags**: typescript, webdev Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. This definition is picking from the typescript documentation. The tuple type is a powerful type that helps you to identify the types of elements in an array, you can create special types where the elements of the array can have different types. A simple example ```ts type Point = [number, number]; const point1: Point = [10, 10]; const point2: Point = [10, "10"]; // Type 'string' is not assignable to type 'number' const point3: Point = [10, 10, 20]; // Type '[number, number, number]' is not assignable to type 'Point'. Source has 3 element(s) but target allows only 2. ``` In this case, you can see how the point type is composed by a fixed array of two elements of type number. You can see how typescript detects this constraint and it raises an error when you try to create a point with the second element of type string or you try to create a point with 3 elements. To show you the power of this type, here's another example ```ts type QueryStringItem = [string, number | string | boolean]; const queryStringItem1: QueryStringItem = ["key1", 10]; const queryStringItem2: QueryStringItem = ["key2", "value2"]; const queryStringItem3: QueryStringItem = ["key3", false]; const queryStringItem4: QueryStringItem = ["key3", { value: "value" }]; // Type '{ value: string; }' is not assignable to type 'string | number | boolean'. ``` In this case, you can see how the second element of the Tuple can be a [union type](https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l) of the types: number, string, or boolean; so typescript let you set the second element of the Tuple with one of these last three types. If you try to set the second element with a different type from number, string or boolean the typescript compiler raises an error. That's all from the Tuple type. See you soon guys! --- ### Part 13 of 21: Typescript - Tips & Tricks - Non-null assertion operator - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-non-null-assertion-operator/ - **Published**: Mar 15, 2021 - **Tags**: typescript, webdev In some cases, you have a field that you initialize in a method, and if you follow the flow of the code you are sure that this field is initialized but typescript doesn't understand it. An example ```ts type Person = { name: string; }; let person: Person; function initialize() { person = { name: "name" }; } initialize(); console.log("Hello", person.name); // Variable 'person' is used before being assigned. ``` In this case, you can see how the typescript compiler doesn't understand that the "person" field isn't null but it's initialized. To resolve this problem, the typescript language exposes us the _"Non-null assertion operation"_(!). This operator says to the compiler that the field isn't null or undefined but it's defined. The previous example can be reviewed in this way ```ts type Person = { name: string; }; let person: Person; function initialize() { person = { name: "name" }; } initialize(); console.log("Hello", person!.name); ``` As you can see, in this case, the code doesn't have errors and the compilation ends with success. That's all for today! Bye-bye guys! --- ### Part 14 of 21: Typescript - Tips & Tricks - Never type - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-never-type/ - **Published**: Mar 17, 2021 - **Tags**: typescript, webdev Today I want to talk about the [never type](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type). As you can understand, this type identifies a piece of code that will never be executed or represents a state that shouldn’t exist. Here an example ```ts const throwException: () => never = () => { throw new Error(); }; throwException() console.log('never called'); ``` In this simple example, you can see how the "throwException" method never permits the code execution of the console.log. In this case, the "throwException" method returns the _never_ type because the method doesn't return any value but throws an error. To better understand the never type I show you another simple example ```ts type Square = { kind: "square"; size: number; }; type Rectangle = { kind: "rectangle"; with: number; height: number; }; type Circle = { kind: "circle"; radius: number; }; type Shape = Square | Rectangle | Circle; const area = (shape: Shape): number => { if (shape.kind === "square") return shape.size * shape.size; if (shape.kind === "rectangle") return shape.with * shape.height; // if (shape.kind === "circle") return shape.radius * 2 * Math.PI; const _exhaustiveCheck: never = shape; // Type 'Circle' is not assignable to type 'never'. return _exhaustiveCheck; }; ``` In this example, you can see how the "area" method detects the kind of the shape and it calculates the relative area. I leave the circle type comment voluntarily, so I can show you the power of the never type. At the end of the area method, you can see how the code assigns the shape to the field "_exhaustiveCheck" of type _never_. In this case, the typescript language detects that if you pass a circle shape at the area method, the line "const _exhaustiveCheck: never = shape;" will be executed, so it notifies you raising an error. The typescript language detects that the never type could be executed at runtime so it tries to prevent this problem. To fix this problem the previous method can be reviewed in this way ```ts type Square = { kind: "square"; size: number; }; type Rectangle = { kind: "rectangle"; with: number; height: number; }; type Circle = { kind: "circle"; radius: number; }; type Shape = Square | Rectangle | Circle; const area = (shape: Shape): number => { if (shape.kind === "square") return shape.size * shape.size; if (shape.kind === "rectangle") return shape.with * shape.height; if (shape.kind === "circle") return shape.radius * 2 * Math.PI; const _exhaustiveCheck: never = shape; return _exhaustiveCheck; }; ``` Now the code is compiled successfully and the never type is assigned correctly. From the never type it's all. See you soon guys --- ### Part 15 of 21: Typescript - Tips & Tricks - Assert Function - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-assert-function/ - **Published**: Mar 19, 2021 - **Tags**: typescript, webdev There are times that we need to create some assertions to be sure an object respects some rules. A common case is to check if an object is defined; to do this you can create a simple assertion function like this ```ts function assert(condition: unknown, message: string): asserts condition { if (!condition) throw new Error(message); } ``` To leave you a simple case of use, I write this simple example ```ts type Person = { name: string; email?: string; }; function loadPerson(): Person | null { return null; } let person = loadPerson(); function assert(condition: unknown, message: string): asserts condition { if (!condition) throw new Error(message); } assert(person, "Person is not defined"); // Error: Person is not defined console.log(person.name); ``` As you can see, in this example, the assert function detects if the person is defined and if the person isn't defined the assert function throws an error with the message that you pass in the parameters. To level up, and explain better the power of the assert function, here another example ```ts type Square = { kind: "square"; size: number; }; function ensureSquare(obj: unknown): asserts obj is Square { if ( typeof obj === "object" && !!obj && "kind" in obj && (obj as Square).kind === "square" ) return; throw new Error("Object isn't a Square type"); } const square = { kind: "square", size: 10 }; ensureSquare(square); // const square: Square console.log("shape", square.kind); console.log("size", square.size); const rectangle = { kind: "rectangle", width: 10, height: 15 }; ensureSquare(rectangle); // throw new Error("Object isn't a Square type"); console.log("shape", rectangle.kind); console.log("size", rectangle.size); ``` In this case, you can see how the "ensureSquare" function creates an assertion to detect if the object passed as parameter is of type Square or not. If you see the part of the example where I created the square field, you can note that the type of the square field is `{ kind: string; size: number; }`. If you observe the type of the square field after the "ensureSquare(square);" you can see how typescript converts the type of the field from `{ kind: string; size: number; }` to Square. This conversion is done because if the code passes the "ensureSquare" function you are sure that the "square" field is of type Square. On the contrary, in the second part of the example, the "rectangle" field, on runtime, throws an error, and the code after the "ensureSquare" function will never be executed. I think you have understood the power of the assertion functions, and I hope they will help you to prevent some future mistakes. It's all guys, Bye Bye! --- ### Part 16 of 21: Typescript - Tips & Tricks - Type Guard - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-type-guard/ - **Published**: Mar 22, 2021 - **Tags**: typescript, webdev There are some cases, where we need to detect the type of the object to get the correct implementation of our method. Let me show you a case ```ts type Square = { size: number; }; type Rectangle = { with: number; height: number; }; type Circle = { radius: number; }; type Shape = Square | Rectangle | Circle; const area = (shape: Shape) => { if ("size" in shape) return shape.size * shape.size; if ("with" in shape) return shape.with * shape.height; if ("radius" in shape) return shape.radius * 2 * Math.PI; }; ``` In this case, in the area method, we need to detect the type of the shape to return the correct result. Here we detect the type of the shape in the if condition but typescript permits us to create a special function that identifies if a type is of a specific type or not. These functions are created to have Type Guards that help the compiler, the intellisense, and us to understand the correct type of the object. To show you this function in action, the previous example can be rewritten in this way. ```ts Square = { size: number; }; type Rectangle = { with: number; height: number; }; type Circle = { radius: number; }; type Shape = Square | Rectangle | Circle; function isSquare(shape: Shape): shape is Square { return "size" in shape; } function isRectangle(shape: Shape): shape is Rectangle { return "with" in shape; } function isCircle(shape: Shape): shape is Circle { return "radius" in shape; } const area = (shape: Shape) => { if (isSquare(shape)) return shape.size * shape.size; if (isRectangle(shape)) return shape.with * shape.height; if (isCircle(shape)) return shape.radius * 2 * Math.PI; }; ``` As you can see, the methods: isSquare, isRectangle, and isCircle get a shape as parameter and return a boolean value. If the result is true the shape parameter corresponds to the type indicated to the right of the is keyword, otherwise, it corresponds to another type. I hope this feature will help you in the future and improve the reading of your code. It's all Guy! See you soon! --- ### Part 17 of 21: Typescript - Tips & Tricks - Conditional Type - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-conditional-type/ - **Published**: Mar 24, 2021 - **Tags**: typescript, webdev In some cases, we need to detect if an object/type has specific properties or characteristics. Let me show you a simple case ```ts type TypeName = T extends string ? "string" : T extends number ? "number" : T extends bigint ? "bigint" : T extends boolean ? "boolean" : T extends undefined ? "undefined" : T extends symbol ? "symbol" : T extends Function ? "function" : T extends null ? "null" : "object"; const typeName = (obj: T): TypeName => { if (obj === null) return "null" as TypeName; return typeof obj as TypeName; }; const stringType = typeName('string'); // "string" const numberType = typeName(10); // "number" const bigIntType = typeName(10n); // "bigint" const booleanType = typeName(true); // "boolean" const undefinedType = typeName(undefined); // "undefined" const symbolType = typeName(Symbol()); // "symbol" const functionType = typeName(() => 'result'); // "function" const nullType = typeName(null); // "null" const objectType = typeName({ name: 'name'}); // "object" ``` In this example, we return the type of the parameter as a string, but I want to focus on the TypeName type. This type as you can see, returns the values based on some conditions. In this case, the conditions are based on the parameter's type, but my goal is to show you that you could check if a type respects some conditions or not and act accordingly. This feature is called Conditional Types. To show you the power of this feature here a funny example found in the net :) ```ts type SnackBars = { name: "Short Chocolate Bars"; amount: 4; candy: true; }; type Gumballs = { name: "Gooey Gumballs"; color: "green" | "purples"; candy: true; }; type Apples = { name: "Apples"; candy: true; }; type Cookies = { name: "Cookies"; candy: true; peanuts: true; }; type SnickersBar = { name: "Snickers Bar"; candy: true; peanuts: true; }; type Toothpaste = { name: "Toothpaste"; minty: true; trick: true; }; type Pencil = { name: "Pencil"; trick: true; }; type HalloweenTricksAndSweets = | SnackBars | Gumballs | Apples | SnickersBar | Cookies | Toothpaste | Pencil; type AllCandies = T extends { candy: true } ? T : never; type AllTricks = T extends { trick: true } ? T : never; type AllCandiesWithoutPeanuts = T extends { candy: true } ? (T extends { peanuts: true } ? never : T) : never; type Candies = AllCandies; // SnackBars | Gumballs | Apples | SnickersBar | Cookies type Tricks = AllTricks; // Toothpaste | Pencil type CandiesWithoutPeanuts = AllCandiesWithoutPeanuts; // SnackBars | Gumballs | Apples ``` In this example, you can see how the AllCandies type creates a new type (Candies) composed of all the HalloweenTricksAndSweets that contain the candy property with the true value. The AllTricks type creates a new type (Tricks) composed of all the HalloweenTricksAndSweets that contain the trick property with the true value. The last case AllCandiesWithoutPeanuts is interesting: we get all the candies that don't contain the peanuts property with the true value. I think this funny example can express best the potential of the Conditional Type, and it can help you to understand better all the benefits it can lead to. It's all for today. I hope this feature will help you in the future as it helped me in some cases. See you soon Guys! --- ### Part 18 of 21: Typescript - Tips & Tricks - infer keyword - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-infer-keyword/ - **Published**: Mar 26, 2021 - **Tags**: typescript, webdev Today I talk about the infer keyword. Sometimes, we need to get the value type of an array or get the return type of a function. To do this I need to introduce the infer keyword. To explain this feature I show you an example ```ts type UnboxingArray = T extends Array ? Member : T; type UnboxingArrayString = UnboxingArray; // string type UnboxingArrayNumber = UnboxingArray; // number type UnboxingString = UnboxingArray; // string ``` As you can see, in the UnboxingArray type, we can detect if the T type extends an array and if so we can infer the element type or else we return the T type. As a demonstration, if you see the type of the UnboxingArrayString and the UnboxingArrayNumber you can note how the UnboxingArray infers the string and the number type. In contrast, in the UnboxingString, the UnboxingArray can't infer the type of the elements because the type doesn't extend an array so it returns the string type. Now I show you the infer keyword applied to the function result. ```ts type ReturnType = T extends (...args: unknown[]) => infer R ? R : never; function getPerson() { return { name: "name", surname: "surnmae", }; } type Person = ReturnType; /** type Person = { name: string; surname: string; } */ type StringResult = ReturnType; // never ``` In this example, you can note that if the T type extends a function, the ReturnType infers the type of the function result otherwise it returns the never type. To demonstrate it, you can see how the Person type is composed of a name and a surname fields on the contrary the StringResult is of the never type. Great news for us, the [ReturnType](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) is already included inside of the Typescript types. It's all guys. Bye bye --- ### Part 19 of 21: Typescript - Tips & Tricks - Mapped Types - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-mapped-types/ - **Published**: Mar 29, 2021 - **Tags**: typescript, webdev In some cases, we need to manipulate some types to create new types. In these cases, we have to use the Mapped Types. Let's start explaining the structure of the mapped types. ```ts type MappedTypeExample = { [Key in "x" | "y" | "z"]: number; }; ``` As you can see, a mapped type is a type composed of defined keys and their values, but the power of the mapped types goes out when we want to joke with a generic type. ```ts type Point = { readonly x: number; y: number; z?: number; }; type MappedType = { [K in keyof T]: T[K]; }; type mappedPoint = MappedType; /** type mappedPoint = { readonly x: number; y: number; z?: number | undefined; } */ ``` In this simple example, I show you how to replicate the same object using the mapped type. Now let's add two simple bits to transform our type into new "different" types. The mapped type permits you to add(+) or remove(-) the read-only modifier from your type but also to add(+) or remove(-) the optional modifier. I leave you two simple examples to show these cases. ```ts type MappedPointPlusModifier = { +readonly [K in keyof T]: T[K]; }; type mappedPointPlusModifier = MappedPointPlusModifier; /** type mappedPointPlusModifier = { readonly x: number; readonly y: number; readonly z?: number | undefined; } */ type MappedPointMinusModifier = { [K in keyof T]-?: T[K]; }; type mappedPointMinusModifier = MappedPointMinusModifier; /** type mappedPointMinusModifier = { readonly x: number; y: number; z: number; } */ ``` _N.B. The add(+) modifier isn't indicated in common cases because it is implied_ The mapped types are a powerful feature to manipulate our types and they are used by the typescript team to expose to us some advanced types, but this is a topic of a future post. Before ending I leave you another example to show what you can do with the mapped type. In this example, I transform the Point type to another Point type where the fields aren't exposed directly but they are wrapped by a "get" and "set" method. ```ts type Getters = { [K in keyof T as `get${Capitalize}`]: () => T[K]; }; type Setters = { [K in keyof T as `set${Capitalize}`]: (value: T[K]) => void; }; type WithGetterAndSetter = Getters & Setters; type Point = { x: number; y: number; }; type WithGetterAndSetterPoint = WithGetterAndSetter; /** type WithGetterAndSetterPoint = { getX(): number; setX(value: number): void; getY(): number; setY(value: number): void; } */ ``` It's all for today! See you soon guy! --- ### Part 20 of 21: Typescript - Tips & Tricks - Advanced Types - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-advanced-types/ - **Published**: Mar 31, 2021 - **Tags**: typescript, webdev Hi Guys, Today I'll show you some advanced utilities exposed by the typescript language. Let's start! ## Utilities for Types * [Partial](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) This utility allows you to add the optional modifier to all the properties of your type. ```ts type PartialPoint = Partial<{ x: number; y: number }>; // { x?: number | undefined; y?: number | undefined; } ``` * [Required](https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype) This utility allows you to remove the optional modifier to all the properties of your type. ```ts type RequiredPoint = Required<{ x?: number; y?: number }>; // { x: number; y: number; } ``` * [ReadOnly](https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype) This utility allows you to add the read-only modifier to all the properties of your type. ```ts type ReadOnlyPoint = ReadOnly<{ x: number; y: number }>; // { readonly x: number; readonly y: number; } ``` * [Pick](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys) This utility allows you to get a subset of properties from another type. ```ts type PickPoint = Pick<{ x: number; y: number }, "x">; // { x: number; } ``` * [Omit](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) This utility allows you to exclude some properties from another type. ```ts type OmitPoint = Omit<{ x: number; y: number }, "x">; // { y: number; } ``` * [Record](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype) This utility allows you to map the properties of a type to another type. ```ts type Point = { x: number; y: number; }; type PointRecord = Record; // { x: number | null; y: number | null; } ``` * [Exclude](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludetype-excludedunion) This utility allows you to remove some types from a [union type](https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l). ```ts type ExcludeType = Exclude<"x" | "y", "x">; // "y" ``` * [Extract](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union) This utility allows you to get some types from a [union type](https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l). ```ts type ExtractType = Extract<"x" | "y", "x">; // "x" ``` * [NonNullable](https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype) This utility allows you to remove the _undefined_ and _null_ types from a [union type](https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l). ```ts type NonNullableType = NonNullable; // string | number ``` ## Utilities for Function and Class * [Parameters](https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype) This utility allows you to extract from a function its parameters. ```ts function createPoint(x: number, y: number) { return { x, y }; } type ParametersType = Parameters; // [x: number, y: number] ``` * [ConstructorParameters](https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype) This utility allows you to extract from a class its constructor parameters. ```ts class Point { constructor(x: number, y: number) {} } type ConstructorParametersType = ConstructorParameters; // [x: number, y: number] ``` * [ReturnType](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) This utility allows you to get the return type from a function. ```ts function createPoint(x: number, y: number) { return { x, y }; } type CreatePointReturnType = ReturnType; // { x: number; y: number; } ``` * [InstanceType](https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype) This utility allows you to construct a type consisting of the instance type of a construction function type. ```ts class Point { constructor(x: number, y: number) {} } type InstanceTypePoint = InstanceType; // Point type InstanceTypeString = InstanceType; // Error: Type 'string' does not satisfy the constraint 'new (...args: any) => any' ``` * [ThisParameterType](https://www.typescriptlang.org/docs/handbook/utility-types.html#thisparametertypetype) This utility allows you to extract the [this parameter](https://dev.to/puppo/typescript-tips-tricks-this-parameter-7n6) from a function type, or unknown if the function type has no this parameter. ```ts function toHex(this: Number) { return this.toString(16); } function numberToString(n: ThisParameterType) { return toHex.apply(n); } numberToString(12) ``` * [OmitThisParameter](https://www.typescriptlang.org/docs/handbook/utility-types.html#omitthisparametertype) This utility allows you to remove the [this parameter](https://dev.to/puppo/typescript-tips-tricks-this-parameter-7n6) from a function type. ```ts function toHex(this: Number) { return this.toString(16); } const fiveToHex: OmitThisParameter = toHex.bind(5); fiveToHex() ``` ## Utilities to Manipulation String Types * Uppercase This utility allows converting your types to uppercase format. ```ts type StringUppercase = Uppercase<"getX" | "getY" | "setX" | "setY">; // "GETX" | "GETY" | "SETX" | "SETY" ``` * Lowercase This utility allows you to convert your types to lowercase format. ```ts type StringLowercase = Lowercase<"getX" | "getY" | "setX" | "setY">; // "getx" | "gety" | "setx" | "sety" ``` * Capitalize This utility allows you to convert your types to capitalize format. ```ts type StringCapitalize = Capitalize<"getX" | "getY" | "setX" | "setY">; // "GetX" | "GetY" | "SetX" | "SetY" ``` * Uncapitalize This utility allows you to convert your types to uncapitalize format. ```ts type StringUncapitalize = Uncapitalize<"GetX" | "GetY" | "SetX" | "SetY">; // "getX" | "getY" | "setX" | "setY" ``` I hope these utilities will help you in the future. That's all for today. See you soon Guys! --- ### Part 21 of 21: Typescript - Tips & Tricks - Rest Parameters & Rest Arguments - **URL**: https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-rest-parameters-rest-arguments/ - **Published**: Apr 2, 2021 - **Tags**: typescript, webdev Hi guy and welcome back :) Today I'll talk about the Rest Parameters and the Rest Arguments. Sometimes we need to write a simple code like this: ```ts function multiply(a: number, b: number): number { return a * b; } const result1 = multiply(2, 2); // 4 const result2 = multiply(2, 3); // 3 ``` but after a while the customer asks us to multiply for unbounded numbers, so we need to change our code. In these cases, typescript helps us with a feature called Rest Parameters. This feature permits us to identify this list of parameters as an array type so we can leave our consumer to call the method with the correct number of items he needs, and we can manipulate these parameters more easily. Therefore the previous example can be transformed in this way ```ts function multiply(a: number, ...args: number[]): number { return args.reduce((acc, curr) => acc * curr, a); } const result1 = multiply(2, 2, 2); // 8 const result2 = multiply(2, 3, 2, 2); // 24 ``` As you can see, now the consumer can call the "multiply" method as he prefers and our code responds correctly in all cases. In this example, we have called the "multiply" method with a fixed number of elements, 3 in the first case and 4 in the second one. But in some cases, we don't know the correct number of elements and maybe they are in an array. To resolve these cases, typescript has another important feature tied to the Rest Parameters, the Rest Arguments. This feature helps us to convert the array elements to a list of parameters. Thus, we can call the "multiply" method in this way too. ```ts const result1 = multiply(2, ...[2, 2]); // 8 const result2 = multiply(2, ...[3, 2, 2]); // 24 ``` I think that these two features are really powerful, and can help you to manipulate large numbers of parameters and take your code simple and flexible. And now a special greeting. This is the last post of this series [Typescript - Tips & Tricks](https://dev.to/puppo/series/11213), I hope you enjoyed the series and it will help you in your daily work. Many Thanks to have read the series. It's not a goodbye, I'll get back soon with other topics. Bye, Bye Guys! ---