This content originally appeared on Telerik Blogs and was authored by John Au-Yeung
Let’s look at basic TypeScript language features and how we can use them to enhance our Angular apps.
Angular is a framework that lets us create interactive web frontends for users.
It is based on the TypeScript programming language. TypeScript is a superset of JavaScript and it supports all language features included with JavaScript.
TypeScript mainly adds data type checking capabilities that are missing in JavaScript. This makes programming easier since we don’t have to check the data type of variables and other values ourselves.
We can use all TypeScript features in our Angular apps since the Angular CLI comes with the TypeScript compiler built in.
In this article, we will look at basic TypeScript language features and how we can use them in our Angular apps.
Basic TypeScript Language Features
TypeScript comes with some common language features that we use to write programs.
Variable Data Types
One of the basic TypeScript features that we use regularly in our apps is variable declarations.
In JavaScript, we can define variables but we can’t add type annotation to them. But we can add data type annotations to variables with TypeScript.
To declare variables with data type annotations with TypeScript, we write something like:
const a: number = 1;
const b: string = "foo";
We declare a variable a
which is a number
, and variable b
which is a string
. We can assign numbers to number variables.
And we can assign strings to string variables.
If we assign something that doesn’t match the type we specify, we’ll get errors from the TypeScript compiler.
Function Data Types
We can add data type annotations to parameters and return values of functions with TypeScript.
For instance, we write:
const add = (a: number, b: number): number => a + b;
to define the add
function.
It takes parameters a
and b
which are both numbers.
And we specify that the type of the return value of the function is number
after the colon that comes after the function signature. Therefore, we know a + b
is a number.
If we call add
with anything other than two numbers, we will get a type error from the TypeScript compiler. This lets us avoid a lot of mistakes with data types when programming.
Object Data Types
In addition to defining data types for primitive values, we can define data type annotations for objects. There are two ways to define types for objects. One is by defining interfaces and the other is defining a type alias.
To define an interface, we use the interface
keyword.
For instance, we write:
interface Person {
firstName: string;
lastName: string;
}
to define the Person
interface that has the firstName
and lastName
string properties.
Then we can use it as the type for a variable by writing:
interface Person {
firstName: string;
lastName: string;
}
const person: Person = { firstName: "jane", lastName: "smith" };
to define the person
variable of type Person
. We set it to an object with the firstName
and lastName
properties to
match the type.
The object having the same property names and the same types for the properties will make the object match the type.
We can define a type alias with the type
keyword. For instance, we write:
type Person = {
firstName: string;
lastName: string;
};
const person: Person = { firstName: "jane", lastName: "smith" };
to define the Person
type. And we set the person
variable to the same value to match the type specification.
The difference between an interface and a type is that an interface can inherit from other interfaces.
For instance, we write:
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
const dog: Dog = { name: "jane", breed: "poodle" };
to define the Animal
interface and the Dog
interface that inherits from the Animal
interface. And we define the dog
variable of type Dog
that has both properties. This is because Dog
inherits properties from Animal
.
We can inherit from interfaces but not types. Also, we can make properties optional in an interface or type.
To make the age
property optional, we put a question mark after the property name in the Person
interface:
interface Person {
firstName: string;
lastName: string;
age?: number;
}
We can also add dynamic properties into interfaces and types with index signatures.
For instance, we write:
interface Dynamic {
[key: string]: any;
}
const obj: Dynamic = { foo: 1, bar: 2 };
to define the Dynamic
interface that takes any string property keys and we can set them to any type.
As a result, we can set obj
to an object with any property with string keys since it has the Dynamic
type.
Union and Intersection Types
We can combine multiple types into one. One way is to define an union of two types. And the other is to define an intersection of two types.
Variables of a union type can be assigned to anything that matches one of the types listed or a combination of them.
Variables of an intersection type need to have values that match all the types listed combined.
For instance, we write:
type Foo = {
foo: string;
};
type Bar = {
bar: number;
};
type Baz = Foo | Bar;
const x: Baz = { foo: "foo" };
const y: Baz = { bar: 1 };
const z: Baz = { foo: "foo", bar: 1 };
to define the Foo
and Bar
type aliases and assign the union of them to Baz
.
We define the x
, y
and z
variables with type Baz
that’s assigned to an object that has the foo
or bar
properties or both properties together. And they’re all valid since they have at least one of the properties listed.
We can also have unions of primitive types.
For instance, we write:
type NumberOrString = number | string;
const x: NumberOrString = 1;
const y: NumberOrString = "foo";
to define the NumberOrString
type which is a union of number
or string
. And we can assign variables with the type to a number or a string.
We can define intersection types with &
. For instance, we write:
type Foo = {
foo: string;
};
type Bar = {
bar: number;
};
type Baz = Foo & Bar;
const x: Baz = { foo: "foo", bar: 1 };
to define the Baz
type which is an intersection of the Foo
and Bar
types.
Therefore, variables of type Baz
need to have both the foo
and bar
properties since intersection types combine both types into one.
Class Decorators
In TypeScript, class decorators is a function that manipulates constructor functions.
For instance, we write:
const sealed = (constructor: Function) => {
Object.seal(constructor);
Object.seal(constructor.prototype);
};
@sealed
class C {
name: string;
constructor(t: string) {
this.name = t;
}
}
to define the sealed
constructor that takes the constructor
function.
And we call Object.seal
with constructor
and constructor.prototype
to stop us from modifying the constructor
and its prototype
after it’s defined.
We put the decorator right above the class C
to modify class C
with the operations in the sealed
constructor.
Classes are just constructors with a convenient syntax in JavaScript and TypeScript, so they’re the same.
Decorators are used for many classes in Angular including components.
Enums
Enums is a data type that can take a set of predefined values. TypeScript has enums built in as a language feature. We can define one
with the enum
keyword.
For instance, we write:
enum Fruit {
APPLE,
ORANGE,
BANANA,
}
const fruit: Fruit = Fruit.APPLE;
to define the Fruit
enum with a few choices.
Then we can use the enum name as the type and set the variable to one of the enum values.
Using TypeScript Features in Angular
We can use all the TypeScript language features with Angular. The ng generate
command,
or ng g
command for short, lets us create various TypeScript entities automatically.
We can use it to create a class, enum or interface files.
For instance, we run:
ng g class MyClass
ng g interface MyInterface
ng g enum MyEnum
to create class, interface and enum files automatically.
The file will have one class, interface or enum that’s exported with export
.
For instance, we run:
ng g interface Person
to create the src/app/person.ts file.
It it, we change it to:
export interface Person {
firstName: string;
lastName: string;
}
to add the firstName
and lastName
fields to it.
Then in app.component.ts
, we write:
import { Component } from "@angular/core";
import { Person } from "./person";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
person: Person = {
firstName: "jane",
lastName: "smith",
};
get fullName() {
const { person } = this;
return `${person.firstName} ${person.lastName}`;
}
}
to import the Person
interface we just created and set that as the type for the person
instance variable in the AppComponent
class.
We also add a getter to return the value of the firstName
and lastName
combined as fullName
.
In app.component.html
, we write:
<p>{{ person.firstName }}</p>
<p>{{ person.lastName }}</p>
<p>{{ fullName }}</p>
to render the values.
As a result, we see:
jane
smith
jane smith
on the screen.
AppComponent
is made a component with the @Component
decorator.
It changes the AppComponent
class to set the HTML selector, template URL and stylesheet URLs.
Also, we set the person
instance variable’s data type to Person
so we can only enter the properties listed in the Person
interface without errors.
We then render the instance variables in the app.component.html
template since we set templateUrl
to app.component.html
as the template path for AppComponent
when we call the Component
function to return a decorator that modifies AppComponent
to be a component.
Conclusion
Angular is based on the TypeScript programming language, a superset of JavaScript that supports all language features included with JavaScript.
TypeScript enhances JavaScript by providing data type checking features that aren’t available with JavaScript. It lets us write code without having to look up the data type for each variable since code editors can provide autocomplete hints by the type definitions.
Having TypeScript type definitions also make code editors aware of the members that are available in objects, classes and modules. It also lets us prevent runtime errors caused by mismatched data types between variables and values when we are doing any operation.
The Angular CLI provides us with commands to create some TypeScript entities with one command.
And we can use any TypeScript language feature in Angular projects created with Angular CLI since it comes with the TypeScript compiler.
This content originally appeared on Telerik Blogs and was authored by John Au-Yeung
John Au-Yeung | Sciencx (2023-05-15T07:41:00+00:00) Angular Basics: A Primer for Getting Started with TypeScript in Angular. Retrieved from https://www.scien.cx/2023/05/15/angular-basics-a-primer-for-getting-started-with-typescript-in-angular/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.