Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
May 21, 2022 01:08 pm GMT

TypeScript for Beginners

A quick view of the everyday types.

TypeScript has been one interesting thing amongst others that has happened to the JavaScript language in recent years. The superset script has indeed made programming in JavaScript not only safer but much more interesting and approachable (especially to developers coming from languages that use compilers).

It goes without saying that the most errors in JavaScript is the type errors. JavaScript inheritly does not provide a type checking system for its code. so one big implication is that developers tend to provide a different value when a certain kind of value was expected.

This article will cover JavaScript's common data types and the equivalent ways to describe and typecheck them using TypeScript. It will not be touching the advanced parts (not necessarily) of TypeScript. What this article will show is the building block of TypeScript code.

Let's go...

This article is simplified version of the everyday types from the TypeScript docs and assumes you know the fundamentals of javascript.

Installing TypeScript.

TypeScript can be installed in 3 ways: through the NPM registry, as a Visual Studio extension, and through the the .NET package registry (NuGet).

You can chose any routes you want for the installation. I have NodeJS installed so that's what I'll be using.

Visit here to download TypeScript.

If you want to jump straight into code while following, you can use this TypeScript playground.

Everyday Types

The essence of TypeScript is provide make for what the language lacked the most a static typechecker. A typechecker runs before the actual code runs to ensure all data types are correct (typechecked) and are used as they should in a program.

Annotating Primitives

JavaScript has three basic primitives data types: string,number and boolean. These form the basic level types in the language.

  • String represent text like "Hi Romeo".
  • Number represent number like 5. Every digit in JavaScript represented as number. There aren't special representation like int and float
  • Bolean represent two values, true and false.

Below is the representation of primitves in JavaScript and the equivalent in TypeScript.

// JavaScriptconst name = "Romeo";const age = 23;const isChristian = true;
// TypeScriptconst name: string = "Romeo";const age: number = 23;cont isChrisian: boolean = true;

NOTE:

TypeScript is capable of inferring types automatically in your code. For example, the type of a variable is inferred based on the type of its initializer:


let myName = "Alice";

No type annotation needed 'myName' inferred as type 'string'

Arrays

The represent types of an array, say a string of names like ["Romeo","Uwan',"Peter"]. you can use the string[] sytax to do so. It works for other types as well, like numbers (number[]).

// JavaScriptconst names = ["Romeo", "Uwan", "Maxwell", "Peter"];const numbers = [23, 5.5, 42, 32];
// Typescriptconst names: string[] = ["Romeo", "Waan", "Maxwell", "Peter"];const numbers: number[] = [23, 5.5, 42, 32];

Any

The any type is special to TypeScript and will cause a value not be validated by TypeScript for its type. In other words, it won't be typechecked.

When a value has the any type, it and its property can be accessed and manipulated as you normally would in JavaScript without it's being typechecked. That means it can be assigned to (or from), called as a function and it's property, which in turn has type of any, can be accessed.

// Typescriptlet someVariable: any = {name: "Romeo"};someVariable.bar = 100;someVariable = (n=10) => n;someVariable();

NOTE:

The any type can be disabled using the noImplicitAny flag. You'll learn more about TypeScript configuration as we proceed.

<-- Describe noImplicitAny in .ts configutation file -->

Functions

Function annotation in TypeScript are of two types: Parameter Type Annotation and Return Type Annotation.

Parameter Type Annotation

When you declare a function you can annotate the parameters to indicate types of parameters the function expects. parameter type annotation come after the parameter is declared, like so:

// JavaScriptfunction greetRomeo(name) {    console.log("Hey Romeo, I'm " + name);}
// TypeScriptfunction greetRomeo(name: string) {    console.log("Hey Romeo, I'm " + name);}

Any argument passed to the greetRomeo function will be checked. In the case above, the name parameter expect a string agument, any thing else, say a number, will show an error.

NOTE:

TypeScript is strict about the number of parameters passed to a function. Even without annotation, it'll check that you passed in the right number arguments.

Return Type Annotation

You can annotate the returned value from a function. Anything value return that doesn't match type annotated will be flag for error.

JavaScriptfunction getAge() {    return 23}
TypeScriptfunction getAge(): number {    return 23}

Typescript can infer the return type based on the value return. Annotating the type value is mostly for documentation purposes.

Personally, I take documentation quite seriously. Fellow developers shouldn't have to peel their scalp to understand what codebase does.

Anonymous function

When a function is a passed as a callback (most often anonymous functions), TypeScript can determine how that function will be called thus inferring the paramater type for such functions.

// No type annotations here, but TypeScript can spot the bugconst names = ["Romeo", "Waan", "Peter"];// Contextual typing for functionnames.forEach(function (s) {  console.log(s.toUppercase()); // Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?});// Contextual typing also applies to arrow functionsnames.forEach((s) => {  console.log(s.toUppercase()); // Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?});

Notice that the s parameter for both functions pure and arrow is not annotated, yet TypeScript could infer the correct type because it knows how the anonymous function will work on an array in that context. This is called contextual typing because the context where the function is used is known to TypeScript thus it (TypeScript) can infer the type the function should have.

Object types

Beside primitives, a common form of data type you deal with as a JavaScritp developer is an Object; this is any JavaScript data type with properties and values.

To define an object type, you list the properties and their types. For instance, here's a function that takes an object as a parameter.

// JavaScriptfunction romeosProfile(profile){    if (typeof profile === "Object") {        console.log("Romeo's age is " + profile.name);        console.log("Romeo's height is " + profile.height);    }}romeosProfile({name: "Romeo", age: 23});
// TypeScript// The parameter's type annotation is an object typefunction romeosProfile(pt: {name: string, age: string}){    console.log("Romeo's age is " + pt.name);    console.log("Romeo's height is " + pt.height);}romeosProfile({name: "Romeo", age: 23});

The parameter of the function is annotated as an object type. the further annotation of the object type itself is optional which, if done so, will have a type of any.

Optional properties

Object types can specify some optional properties by appending a ? after the property name.

function romeosProfile(obj: {name: string, age?: number}) {  // ...}// Both OKprintName({ name: "Romeo" });printName({ name: "Romeo",  age: 23 });

Say you didn't provide an argument for the optional parameter and you accessed it, it will return undefined because the property doesn't exist. When reading from an optional property, make sure to check that it's not undefined.

function romeosProfile(pt: {name: string, age?: number}) {  // Error - might crash if 'pt.age' wasn't provided!  console.log(pt.age);  if (pt.age !== undefined) {    // OK    console.log(pt.age);  }  // A safe alternative using modern JavaScript syntax:  console.log(pt.age?);}

Combining Types in TypeScript

The type system in TypeScript allows you to combine and form new types from existing ones.

Union Type

A union type is a type formed by combing two or more other types that represent values of any of the existing types. the combine types are referred to as the union's member.

Here is function that accept and string and number as it's parameter.

function printAge(age: number | string) {    console.log("i'm " + " years old");}printAge(23) // I'm 23 years oldprintAge("23") // I'm 23 years oldprintAge({age: 23}) // Error

Working with Union Type

TypeScript will only allow an operation if it's valid (intersection of type property) for either of the union member. For instance, you can't perform a toUpperCase operation on a string | number union and that's because the operation is only valid for value with type of string but the type value could be a number.

To get around union type who's property may not intersect, you use Narrowing to "... deduce a more specific type for a value based on the structure of the code."

For instance, using a conditional to let TypeScript know that an operation for a certain type.

function printAge (age: number | string) {    if (typeof age === "string") {        console.log(age.toUpperCase());    } else {        // age is type of 'number'        console.log(age)    }}

or if member of union type is an array:

function meetFriends(x: string[] | string) {    if (Array.isArray(x)) {        console.log("Hello, " +  x.join(" and ") + ". Nice to meet you all!")    } else {        // is a string and not an array        console.log("Hello " + x);    }}

As indicated earlier, members of a union type whose value share (intersect) properties don't need narrowing:

function getFirstTime(x: number[] | string) {    return x.slice(0, 3);}

Type Aliases

Type aliases allows you to name a type and use it more than once by only referring to it by name. It is a name for any type.

Object aliase typetype Profile = {    name: string,    age: number}// Union Type aliase typetype ID = number | string;

With the Profile type Aliase above, you can pass it as parameter type for a function by simping referring to the name (Profile).

// Type Profile creates a type structure to be used as parameter typefunction getProfile(pt: Point) {    console.log("Name: " + pt.name);    console.log("Age: " + pt.age);}getProfile({name: "Romeo", age: 23});

Interfaces

Interfaces are similar to types aliases, and the two can be used interchangeably to create a named type for an object. The only difference is that a type aliase can't be added new fields when once created, compared to interface that is opened to be added more fields.

Object interfaceinterface Profile = {    name: string,    age: number}// Valid and will be combined with above interfaceinterface Profile = {    eyeColor: string}// Type Profile creates a type structure to be used as parameter typefunction getProfile(pt: Point) {    console.log("Name: " + pt.name);    console.log("Age: " + pt.age);}getProfile({name: "Romeo", age: 23});

It is generally preferred to use interface when creating a named type for objects, just in case you'd want to add to the existing fields.

interface Profile = {    name: string,    age: number,    eyeColor: string}// Object takes the structure of defined interface using Type Assertionconst RomeosProfile: <Profile> {    name: "Romeo",    age: 23,    eyeColor: "black"}

Type Assertions

Type assertion allow you to declare (assert) a type on a variable so that the compiler won't infer it at runtime. This is because you, as the programmer, could have more information of the type of value that TypeScript can't or at least, it'll infer something not quite right.

Type assertion is similar to typecasting in other languages like C++, C# and java except that there is no runtime effect (all assertions are removed by the compiler) in TypeScript.

for instance, if you're accessing the DOM using document.getElementbyId, TypeScript understands that it'll return a HTMLElement, but you might know specifically that it'll be a HTMLCanvasElement.

You can use a type assertion to specify that:

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

You can use the angle-bracket to achieve the same effect.

const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");

Another instance is asserting object, similar to the one you saw earler.

interface Creator {     name: string;     code: number; }// Using the `as` keywordlet person = {} as Creator; // Okperson.name = "Romeo";person.age = 23;// Using angle-bracketlet person = <Creator> {}; // okperson.name = "Romeo";person.age = 23;

NOTE:

When dealing with TypeScript in React (.tsx format), ony the as keyword is allowed because using angle-brackets in JSX will create a conflict in the React code.

Literal Types

With literal types you can create and refer to specific string and number in type positions.

For instance, a variable with a specific string type:

let x: "hello" = "hello";x = "Howdy"; // Type '"howdy"' is not assignable to type '"hello"'.

When combined to form a union, literals can be used to create complex and useful type structure in type positions.

for instance, a funtion with a second paramter that only accepts certain values.

function creator(age: number, name: "Romeo" | "Waan" | "Peter"): void {    console.log(alignment);};creator(23,"middle"); // Argument of type '"middle"' is not assignable to parameter of type '"Romeo" | "Waan" | "Petercreator(23, "Waan") // No error, will log `Waan`

Also, a function that can only return numerical literals:

function compare(a: string, b: string): 1 | -1 | 0 {    return a === b ? 0 : a < b ? 1 : -1;}compare("23", "34"); // No error, will log 1;

Literal types can be combined with non-literal types too.

interface Option {    width: number;}function configure(x: Options | "auto") {  // ...}configure({ width: 100 }); // No errorconfigure("auto"); // No errorconfigure("automatic"); // Error: Argument of type '"automatic"' is not assignable to parameter of type 'Options | "auto"'.

Although we didn't use it, the boolean (true and false) literal type can used to achieve similar concept as the ones abovel.

NOTE:

The boolean type is actually an aliase that represent the union of true and false.

Alrigth, that's about it for the everyday types you'll encounter while using or reading TypeScript code. Before I round up things, let's look into configuring TypeScript using the tsconfig.json. file

TS Config

The TypeScript configuration file is tsconfig.json that sits at the root of project. It's automatically created when the TypeScript is first initialized. The file specifies the root files and compiler options for the project.

Using the .tsconfig to compile project.

There are two ways you can do this:

  • By invoking the tsc CLI command with no input files, in which case the compiler uses the tsconfig.json (starting from the current directory and going the the directory chain) file to look for the project file to compile.
  • By invoking the tsc CLI command with a --project or -p option that specifies the directory to the .tsconfig.json file containing the configuration.

When input files are specified on the command line, the ones specified in the tsconfig.json files are ignored.

Here is a reference to the configuration options you can make as fitting to a project.

Conclusion.

The basis of this article is get you started with building block of TypeScript code. The TypeScript documentation answers questions this article fails to provide. Do check it out.

Let's connect on Twitter, I hear that my tweets are quite intriguing.

Cheers!


Original Link: https://dev.to/romeopeter/typescript-for-beginners-50h0

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To