- Learning Angular
- Aristeidis Bampakos Pablo Deeleman
- 955字
- 2021-06-11 18:24:04
Common TypeScript features
There are some general features in TypeScript that don't apply specifically to classes, functions, or parameters, but instead make coding more efficient and fun. The idea is that the fewer lines of code you have to write, the better it is. It's not only about fewer lines but also about making things more straightforward. There are a ton of such features in ES6 that TypeScript has also implemented. In the following sections, we'll name a few that you are likely going to use in an Angular project.
Spread parameter
A spread parameter uses the same ellipsis syntax as the rest parameters but in a different way. It's not used as a parameter inside of a function, but rather inside its body. Let's illustrate this with an example:
const newItem = 3;
const oldArray = [1, 2];
const newArray = [...oldArray, newItem];
What we do here is add an item to an existing array without changing the old one. oldArray still contains 1, 2, but newArray contains 1, 2, 3. This general principle is called immutability, which essentially means don't change, but rather create a new state from the old state. It's a principle used in functional programming as a paradigm, but also for performance reasons. You can also use a rest parameter on objects, like this:
const oldPerson = { name : 'John' };
const newPerson = { ...oldPerson, age : 20 };
This is a merge between the two objects. Just like with the example of the list, we don't change the previous variable, oldPerson. The newPerson variable takes the information from oldPerson and adds its new values to it.
Template strings
Template strings are all about making your code clearer. Consider the following:
const url = 'http://path_to_domain' +
'path_to_resource' +
'?param=' + parameter +
'=' + 'param2=' +
parameter2;
So, what's wrong with this? The answer is readability. It's hard to imagine what the resulting string will look like, but it is also easy for you to edit the previous code by mistake, and suddenly, the result will not be what you want. Most languages use a format function for this, and that is exactly what template strings are. This can be used in the following way:
const url =
`${baseUrl}/${path_to_resource}?param=${parameter}¶m2={parameter2}`;
This is a much more condensed expression and much easier to read.
Generics
Generics is an expression for indicating a general code behavior that we can employ, regardless of the type of data. They are often used in collections because they have similar behavior, regardless of the type. They can, however, be used on constructs such as methods. The idea is that generics should indicate if you are about to mix types in a way that isn't allowed:
function method<T>(arg: T): T {
return arg;
}
method<number>(1);
In the preceding example, the type of T is not evaluated until you use the method. As you can see, its type varies, depending on how you call it. It also ensures that you are passing the correct type of data. Suppose that the preceding method is called in this way:
method<string>(1));
We specify that T should be a string, but we insist on passing it a value of the number type. The compiler clearly states that this is not correct. You can, however, be more specific on what T should be. You can make sure that it is an array type so that any value you pass must adhere to this:
function method<T>(arg: T[]): T[] {
console.log(arg.length);
return arg;
}
class CustomPerson extends Array {}
class Person {}
const people: Person[] = [];
const newPerson = new CustomPerson();
method<Person>(people);
method<CustomPerson>(newPerson);
In this case, we decide that T should be the Person or CustomPerson type, and that the parameter needs to be of the array type. If we try to pass an object, the compiler will complain:
const person = new Person();
method<Person>(person);
So, why do we do this? We want to ensure that various array methods are available, such as length, and that we, in a given moment, don't care if we operate on something of the CustomPerson or Person type. You can also decide that T should adhere to an interface, like this:
interface Shape {
area(): number;
}
class Square implements Shape {
area() { return 1; }
}
class Circle implements Shape {
area() { return 2; }
}
function allAreas<T extends Shape>(...args: T[]): number {
let total = 0;
args.forEach (x => {
total += x.area();
});
return total;
}
allAreas(new Square(), new Circle());
Generics are quite powerful to use if you have a typical behavior that many different data types can relate to. You most likely won't be writing your custom generics, at least not initially, but it's good to know what is going on.
- WildFly:New Features
- Apache ZooKeeper Essentials
- LabVIEW2018中文版 虛擬儀器程序設(shè)計自學(xué)手冊
- Raspberry Pi for Secret Agents(Third Edition)
- Silverlight魔幻銀燈
- Kinect for Windows SDK Programming Guide
- Spring Boot Cookbook
- Java:High-Performance Apps with Java 9
- HTML5 APP開發(fā)從入門到精通(微課精編版)
- MySQL從入門到精通(軟件開發(fā)視頻大講堂)
- JavaScript程序設(shè)計(第2版)
- Python Interviews
- 跟戴銘學(xué)iOS編程:理順核心知識點(diǎn)
- AMP:Building Accelerated Mobile Pages
- Software Development on the SAP HANA Platform