官术网_书友最值得收藏!

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}&param2={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.

主站蜘蛛池模板: 石泉县| 安溪县| 青阳县| 开原市| 花垣县| 陆丰市| 财经| 同江市| 来凤县| 城口县| 新竹县| 长海县| 西林县| 历史| 商都县| 武夷山市| 长武县| 彩票| 吴堡县| 澄城县| 安阳市| 双柏县| 凯里市| 阿坝县| 彭州市| 兴安县| 萨迦县| 阳谷县| 商城县| 鹤岗市| 龙胜| 元阳县| 临颍县| 二连浩特市| 高清| 江华| 新野县| 阳原县| 大新县| 莲花县| 阿拉善盟|