- 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.
- Bootstrap Site Blueprints Volume II
- Magento 2 Theme Design(Second Edition)
- Mastering Natural Language Processing with Python
- Unity Shader入門精要
- ASP.NET 3.5程序設計與項目實踐
- Mastering Apache Maven 3
- Mastering JavaScript High Performance
- 速學Python:程序設計從入門到進階
- Android驅動開發權威指南
- Getting Started with Polymer
- C++程序設計
- OpenStack Sahara Essentials
- Neo4j權威指南 (圖數據庫技術叢書)
- 像程序員一樣使用MySQL
- ASP.NET 3.5系統開發精髓