Ausnahme gefangen: SSL certificate problem: certificate is not yet valid 📌 How to learn and use TypeScript + the bits no one teaches you.

🏠 Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeiträge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden Überblick über die wichtigsten Aspekte der IT-Sicherheit in einer sich ständig verändernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch übersetzen, erst Englisch auswählen dann wieder Deutsch!

Google Android Playstore Download Button für Team IT Security



📚 How to learn and use TypeScript + the bits no one teaches you.


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

TypeScript spraying away bugs animated

Intro

In this article, I will provide you with tools and a mental framework that will help you learn and work with TypeScript, effectively. I will show you that learning TypeScript from a JavaScript background is not as daunting as it may seem. To achieve this, we will begin by learning the foundational types, but with a slightly different approach that emphasizes practical application. Finally, I will share some tips and tricks that I have picked up through experience, and that you won't find anywhere else.

This is a comprehensive resource aimed to be the last resource you will ever need to start using TypeScript. As such, I recommend breaking up your time reading this article in chunks. Throughout the next sections I will provide you with information that I wish I had known when first learning to use TypeScript.

Please enjoy!

Table of Contents

  1. How To Learn TypeScript
  2. Understanding Type-Safety
  3. The Types You'll Need
  4. Benefiting From Your Coding Environment
  5. How to Read Error Messages
  6. Using TypeScript in a Project Environment
  7. Conclusion

How To Learn TypeScript

Mastering TypeScript requires more than just learning its syntax. Learning the types is a meaningful step, but most importantly, is how to understand the patterns of our code. Please be aware that TypeScript is an aid in development, but it should not been seen as the sole code we are writing. Most of what we are coding is still plain old JavaScript with stated expectations.

Note: All JavaScript is valid TypeScript. Once you transpile your code, all of your TypeScript will turn into JavaScript. More on this in later sections.

Understanding Type-Safety

By adhering to the behavior that is predefined by a type, we can ensure the safety and reliability of our application. This means that, compared to JavaScript, we can often prevent runtime errors that may have otherwise been encountered by users.

The types we'll cover will be familiar terms, such as number, string, boolean, array, and object. The key difference is that TypeScript provides a way to ensure the validity of our values. In contrast, JavaScript lacks such a mechanism, making it tedious and sometimes difficult to guarantee the correctness of values without writing conditions and boilerplate code.

Take a look at the JavaScript example below. To verify that every element of the numbers array is a number, we need to add a check that runs during every iteration.

JavaScript boilerplate

Although the code doesn't seem like much of an inconvenience, did you notice that numbers parameter was never validated as an array? It's easy to miss potential problem area's in our code.

Let's see how we can avoid manually testing edge cases in the next section.

The Types You'll Need

By default, TypeScript has the ability to understand a great deal about our code without requiring any additional effort on our part. This is called inference. Through inference, TypeScript can often determine the type of a value based on its usage.

An easy way to appreciate this phenomenon is to hover over variables, methods, or function declarations in your editor. This can be especially helpful when working with libraries, as hovering over code can reveal valuable insights about data shapes and usage of methods. The best part is that this approach can save time that would otherwise be spent searching for documentation.

While this section introduces types, we will see a structure on hover that resembles: let str: string. To read this as if it were English, we would say that "str is of type string" or "str is a string type". We denote types with the : syntax followed by the type of value we want to store.

As we walk through, I encourage you to visit the TypeScript Playground to test these examples on your own

Type Index

  1. number
  2. string
  3. boolean
  4. any
  5. const
  6. unions
  7. undefined
  8. null
  9. unknown
  10. arrays
  11. objects
  12. parameters
  13. return types
  14. void
  15. methods
  16. generics
  17. custom types
  18. intersections

number

The number type represents any number in JavaScript, including negative numbers, NaN, and Infinity.

Type inference for a number

Number Code Example

string

The string type represents any collection of characters and can be declared with either single or double quotes.

Type Inference for a string

String Code Example

boolean

The boolean type refers to true or false.

Type inference for a boolean

Boolean Code Example

any

The any type typically occurs when the type of a value or variable cannot be inferred, meaning that the type can be "any" type. When writing code, we typically want to be in an any-less environment. Any doesn't provide type-safety, meaning we're essentially operating in JavaScript land.

Type inference for any

Any Type Code Example

const

When we declare a variable with the const keyword, the value is considered Readonly, meaning that the value can never be mutated. In TypeScript, this changes the type of a value from its primitive type to what’s referred to as a literal type, which means that the type of a value is just that value.

Note that const only has the literal type effect for JavaScript primitives (number, boolean, string, symbol, bigint, undefined, and null). This is because no mutations with these types are possible without reassignment, unlike arrays or objects that can gain new properties or elements without being reassigned.

Type Inference for const

Const Code Example

unions

The | operator specifies a union of types. A union allows a variable to hold values of separate types. It's possible to chain together unions of types by using multiple unions in succession.

union types

Union Code Example

undefined

The undefined type occurs when we explicitly define the behavior. We can type something as undefined, but a more common use case happens when we use the optional syntax ? for function parameters or properties of an object type. Defining an optional type will create a union of the specified type and undefined.

Optional Parameters

Undefined Code Example

null

The null type can be used in a few different places, but it's most commonly used in a union as the return type of a function or to store default values of a variable that may change at a later date.

String or null union type

Null Code Example

unknown

The unknown type is most commonly used as a safer, more descriptive way, to define when you don't yet know the type of a value. It's a great choice instead of using any in certain scenarios. It's safer because TypeScript will force us to perform some type of runtime check or type assertion before the value can be used. Although this seems annoying, it allows us to maintain type-safety. A typical use case of unknown could be typing the return of an API call.

making a request

Unknown Code Example

arrays

The array type houses a list of elements of a specific type. Remember that a particular type can mean whatever you make it, which means that if you specify a union type, an array can hold multiple kinds of elements. Two different kinds of syntax can be used to define an array type. The first way and way in which you'll see arrays denoted is to use square brackets []. The second way is to define whats called a type constructor for arrays, Array<number>, which we will cover later with generics.

Array of a union between a string and number

Array Code Example

objects

The object type is a collection of types. Unlike unions, object types are precise declarations and require the usage of the property keys you define and the correct type of values they store. Object types can house as many properties and different kinds of types as you would like, including other object types. You can create an object type by using curly braces {} and adding a property name and the type of the value in the structure of a regular JavaScript object.

Object type with a firstName and lastName property typed as strings

Object Code Example

parameters

As seen before, you will want to type the parameters in a function. This is super helpful for self-documenting and minimally validating the inputs of a function.

Typing function parameters

Parameter Code Example

return types

Return types can be automatically inferred in typescript based on previously typed values. If you take the example from the parameters section, TypeScript already knows the return value will be a number. Let’s switch up the type of one of the variables and add an explicit return type to state our intentions.

Return type of function

Return Code Example

Note that we had to convert b from a string to a number; otherwise, TypeScript would tell us something is wrong.

void

A function that does not return a value is said to return void. This is automatically inferred if a function does not include the return keyword. However, typing the return can give us type-safety within the function, ensuring we aren't unintentionally returning.

Void function return

Void Code Example

methods

Creating method types can be used to define the shape of a function's inputs and return. In the example below, we create the type for a method belonging to an object.

Example of a method being types

Method Code Example

generics

In TypeScript, generics are a way to parameterize types and functions so that they can work with any type instead of a specific one. It's a way to define the structure of a type, while being agnostic to the underlying types that operate under the structure. Generics are commonly seen throughout usage with external JavaScript libraries. They are powerful types, but can be tricky to understand and read errors from.

For our example, I will show you the instance mentioned in the Arrays section where we use the Array constructor. The Array constructor allows us to pass in a type that will comprise the elements of the array.

To learn how to construct your own generic types, feel free to visit: Generics. We will be skipping over the creation of them because they aren't necessary when starting out. Though, it is important see the constructors for these generic types like in the example below.

Array constructor

Generics Code Example

custom types

Creating your own types is valuable when you would like to add further semantic meaning to a type, decrease the size of a type declaration, and/or export a type so it can be used throughout your application. Custom types typically follow the Pascal Case naming convention where the first letter of every word is capitalized including the very first word; "MyCustomType."

type keyword

We can declare our own types in TypeScript using the type keyword, followed by a name and set equal to any type. By using the type keyword we can take any type we previously learned and set it equal to our type.

In the Objects section, we had created a type inline. Let's see what it would look like to abstract an object type into it's own type.

Using the type Keyword

Type Keyword Code Example

Remember, that the curly braces indicate an object type, we can set a type equal to anything, such as primitives, unions, objects, arrays, etc.

interfaces

Using interfaces acts very similar to using the type keyword. They both generate the same thing, but interfaces have a few quirks. Some say it is preference what you use but due to the potential performance implications, it is generally advised to use the type keyword unless you need use of the extends keyword which we will now discuss. The extends keyword can be used in conjunction to to an interface to inherit properties and methods from another type. It's exactly like how you would think about it in Object Oriented Programming. One other key distinction about the interface vs. type keyword is that interfaces must hold Object types and the type keyword can hold anything. Because of this, interfaces do not use an equal sign. Here is an example of an interface with use of the extends keyword.

Typing with interfaces

Interface Code Example

When creating interfaces and object types with the type keyword, you can choose to add commas, semi-colons or nothing at the end of each key/value as long as each property is placed onto it's own line. If not a comma or semi-colon must be used.

intersections

An intersection defines a combination of multiple types. Unlike a union where we specify a type is one type or another type, an intersection will combine the properties of multiple object types into a brand new type. Meaning you must satisfy the behavior of both types combined.

Intersection of types

Intersection Code Example

Benefiting From Your Coding Environment

TypeScript offers more than just error detection and correction. By leveraging TypeScript's type system and writing clean, reusable code, you can build an environment that helps you write better code. TypeScript can identify potential problem areas in your code and suggest solutions, allowing you to avoid errors and write code that is easier to maintain.

Program Predictive Behavior

To make the most of TypeScript, it's important to define the behavior you want to use and follow it throughout development. By extracting repeating code into types and clearly stating your intentions for variables and returns, TypeScript can help guide you towards the right solution. With TypeScript's help, you can write code that is not only correct but also easy to read and maintain.

Let TypeScript Guide You

TypeScript's powerful type system provides you with immediate feedback on potential issues in your code. If you try to assign a value of the wrong type to a variable, TypeScript will generate an error message and show a squiggly line under the offending code. By following TypeScript's guidance, you can become a more efficient and productive developer.

Improved Developer Experience

TypeScript greatly improves your developer experience by providing tools that help you write better code faster. Its editor integration offers intelligent code completion, navigation, and refactoring, allowing you to write code with more confidence and accuracy. TypeScript's strict type checking identifies potential issues in your code early on, giving you more time to build new features instead of fixing bugs. This type safety also works across your entire project, ensuring consistency and reducing the risk of errors. Additionally, TypeScript's support for modern ECMAScript features allows you to take advantage of the latest language features while maintaining compatibility with older browsers.

How to Read Error Messages

Understanding error messages in TypeScript can be challenging, but with practice, it becomes easier. To begin with, it is crucial to understand the expectations of the code you use. This means knowing the expected types of variables, functions, and values.

When you encounter a type error, it can happen in one of two ways:

  1. When you attempt to use a variable, function, or value in a way that breaks its type contract.
  2. When TypeScript needs more information about what you're trying to do to be confident about the behavior.

In both cases, TypeScript will provide an error message to help you understand the issue.

To become proficient at understanding error messages, you need to become familiar with the common patterns of errors that occur. This familiarity will help you recognize pitfalls as they happen, making it easier to debug your code.

For better assistance in reading error messages, you can download the VSCode extension Total TypeScript by Matt Pocock. This extension includes an error translator that takes TypeScript error messages and converts them into a more human readable format.

Common Errors and Why They Happen

While reading through this section, I encourage you to click on the example code and try to solve the type errors. You will have succeeded when the error messages go away. Good Luck!

Type 'x' is not assignable to type 'y': This error occurs when you try to assign a value of a different type to a variable than the type the variable was defined with.

Example of the Error Message: Type 'x' is not assignable to type 'y'

Example of the Error

Solution: Change your code to follow the type contract, or redefine the contract.

Property 'x' does not exist on type 'y': This error occurs when you try to access a property that does not exist on an object.

Example of the Error Message: Property 'x' does not exist on type 'y'

Example of the Error

Solution: The error message will include the shape of the object you are trying to access a property from. Read the definition and make sure to use properties that exist within the type.

Tip: When you type '.' on an object, TypeScript will show you the methods and properties that belong to the object.

Cannot find name 'x': This error occurs when you try to use a variable or name that has not been declared or is not accessible in the current scope.

Example of the Error Message: Cannot find name 'x'

Example of the Error

Solution: Define the variable you are trying to use, consider the scope you are in, and/or check your spelling.

Parameter 'x' implicitly has an 'any' type: This error occurs when you do not explicitly declare the type of a function parameter and TypeScript is unable to infer it.

Example of the Error Message: Parameter 'x' implicitly has an 'any' type

Example of the Error

Solution: TypeScript would like to know more about the usage of your variable. In this case, create a type based on what behavior you want. You can type an element explicitly as 'any' but it is generally unadvised for most cases.

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type: This error occurs when you try to perform an arithmetic operation on a value that is not a number or a BigInt.

Example of the Error Message: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type

Example of the Error

Solution: Verify that you are performing operations that are valid for each type. In certain cases you can cast a value to the right type.

Object is possibly 'null' or 'undefined': This error occurs when you're trying to access a property or method on an object that may be null or undefined.

Example of the Error Message: Object is possibly 'null' or 'undefined'

Example of the Error

Solution: Add type checking before you use properties on a potentially null or undefined object through the use of conditionals.

Tip: You can alternatively use JavaScript's optional chaining operator ?., or in certain cases, TypeScript's Non-null assertion operator ! (to be used with caution) to verify that an object is neither undefined or null and keep your code concise.

Using TypeScript in a Project Environment

Now that we have introduced a collection of types, using TypeScript to our benefit and common errors, let's learn how to actually use TypeScript within a project environment. Throughout this section, I will be showing you how to use TypeScript within a Node.js environment.

Basic TypeScript Project Structure

In TypeScript projects, it's typical to keep all your code in a directory called src located at the root of your project. Similarly, all files and folders related to your project's creation and configuration should also be kept at the root level. Here's an example:

node_modules/
src/
   |_ all of your `.ts` files in here
.gitignore
package-lock.json
package.json
tsconfig.json

What do I do with the tsconfig.json?

When I first began using TypeScript, I struggled to find comprehensive guidance on how to structure my tsconfig.json file. This file defines the rules that our TypeScript code should adhere to, including the code it should support, things to check for, how it should be transpiled, and where it should be transpiled.

As a beginner, I suggest keeping it simple. When you continue to work with TypeScript you will find rules that match your needs. For now, don't stress over it.

The easiest option is to use the following command to generate a template for you.

tsc --init

If you do not have TypeScript globally installed, use npx tsc --init

Using this command will generate a tsconfig.json file with potential rules that can be turned on (by uncommenting). Due to the amount of rules, I find it easier to work from a starter that is less daunting and allows you to iteratively find and add rules.

Visit Compiler Options to find rules that match your needs.

Starter Template

Let's replace the contents of the tsconfig.json file with our own rules:

// tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

How to Run Your Code?

At some point in time, our TypeScript code will need to transpile into JavaScript in order to be ran and understood by node or our browser. Transpilation is when one language is translated it into another.

Normally TypeScript tutorials start off by showing us how to transpile our code with tsc but I will be providing other options that I tend to prefer.

Note: There are many different ways to run TypeScript, what you choose will largely be based off of performance within your workspace.

Using node

The easiest way to execute your code is by running the node command followed by the root file of your project. This command will both transpile and execute your code.

node src/index.ts

Note: You can install the nodemon package to automatically re-execute on change. However, we will cover how to use ts-node-dev which is what I prefer.

Using ts-node-dev

My recommendation is to use this method for the majority of your projects. It's easy to set up and is more performant.

There are ways to make using nodemon performant but the steps are far more involved than the following:

First install ts-node-dev as a devDependency.

npm i -D ts-node-dev

Add the following to your package.json scripts. Using the --respawn flag will re-transpile and execute your project on save.

// pacakage.json
"scripts": {
   "dev": "ts-node-dev --respawn src/index.ts"
},

Run your project

npm run dev

Using TypesSript in your Existing Projects

To start working in a node environment with TypeScript, it's important to understand how declaration files work. As your project grows and you install dependencies, TypeScript will need type information for each dependency to ensure that you can use library code in a type-safe way. Luckily, installing type declarations for your dependencies is usually straightforward: just use the following command for each dependency, as the declarations are often already available for you.

We use the @types/ followed by the name of the dependency.

npm i -D @types/express

Note: Remember to install all TypeScript related tools as devDependencies.

Tips For Migration

If you would like to use TypeScript in an existing project it can be tricky to convert your project from a non-type-safe environment, to one that is. What is generally recommended is to make incremental changes in your code base that allow you to slowly increase the amount of TypeScript coverage you have in your project. I would recommend tackling your project in chunks, following our steps for setting up TypeScript and changing .js files to .ts (.jsx to .tsx in React codebases). After converting the files, you will most likely encounter a handful of "errors" that need to be corrected. All this is, is TypeScript wanting you to create contracts and state expectations about your code.

Best of luck and you will find resources in the conclusion that will help you if you get stuck.

Conclusion

"Fin", end of article

I'm happy that you made it this far! If you found this article helpful and enjoyed learning about TypeScript, consider sharing it with others. Feedback and suggestions for future topics are always welcome.

For further TypeScript exploration, I recommend checking out the TypeScript Handbook and Matt Pocock's free beginner tutorials at Total TypeScript. However, you should now have the tools to begin using TypeScript in your projects.

Sometimes errors may feel overwhelming. For that, I recommend joining the TypeScript Community Discord Server, for help with anything and everything TypeScript.

...













matomo