[TS evolution history -- breaking the dawn] take you to TS step by step

Posted by ShawnD on Mon, 04 Nov 2019 02:08:05 +0100

By Valentino Gagliardi
Translator: front-end wit
Source: valentinog

Last month, I spent 1300 yuan to buy Alibaba's server to learn node and its corresponding framework. Before the 11th, they had activities. The configuration of 1300 now costs only 86 yuan a year and 229 yuan for three years. I really think it's cost-effective. You can click the next step to participate

https://www.aliyun.com/1111/2...

What is TypeScript

The official website is defined as: TypeScript is a superset of JS type. It assumes that we know what is superset and what is typification. For simplicity, you can think of TypeScript as a shell above JavaScript.

TypeScript is a shell, because after compiling, all that remains is simple JS code.

However, the JS engine cannot read TypeScript code, so any TypeScript file should be pre translated, that is, compiled. Only after the first compilation step, the pure JS code is left, which can be run in the browser. Later, you'll see how TypeScript compilation is done.

Now let's remember that TypeScript is a special JS that requires a translation before it can run in a browser.

Why TypeScript

At first, we didn't fully understand why TypeScript made sense You may ask, "what is the purpose of TypeScript?" This is a good question.

In fact, once it finds serious and stupid errors in your code, you'll see the benefits of TypeScript. What's more, TypeScript makes the code well structured and automatic, which is only a small part of TypeScript.

However, it is often said that TypeScript is useless and too clumsy.

There are two sides to everything. TypeScript has many opponents and supporters, but what's important is that TypeScript is a reliable tool, and it will not hurt if it is put in our tool skill pack.

TypeScript configuration

Why configure TypeScript also has a binary file that compiles TypeScript code into JS code. Remember that the browser does not understand TypeScript:

mkdir typescript-tutorial && cd $_
npm init -y

Then install TypeScript

npm i typescript --save-dev

Next, add the following under scripts in package.json, so that we can easily run the TypeScript compiler:

  "scripts": {
    "tsc": "tsc"
  }

tsc represents the TypeScript compiler, which looks for a file named tsconfig.json in the project folder as long as the compiler is running Use the following command to generate a configuration file for TypeScript:

npm run tsc -- --init

After successful execution, message TS6071: Successfully created a tsconfig.json file will be received in the console. You will see a new tsconfig.json file in the project folder. Tsconfig. JSON is a terrible configuration file. Don't panic. We don't need to know every point of it. In the next section, we will introduce the relevant parts of the introduction.

Configure TypeScript compiler

It is best to initialize git repo and submit the original tsconfig.json before opening the file We will keep only a few configuration options and delete everything else Later, you may need to compare the current version with the original.

First, open tsconfig.json and replace all the original content with the following:

{
  "compilerOptions": {
    "target": "es5",
    "strict": true
  }
}

Save and close the file First, you may want to know what tsconfig.json does The configuration file is read by the TypeScript compiler and any code editor with TypeScript support.

  • noImplicitAny true: TypeScript will report an error when a variable does not have a type defined
  • alwaysStrict true: strict mode is the security mechanism of JS, which can prevent unexpected global variables, default this binding, etc When set to "alwaysStrict", TypeScript uses "use strict" at the top of each KS file.

More configuration options are available. As time goes on, you will learn more, because the two choices above are all you need to know when you start learning.

Some words about type

TypeScript supports almost the same data types as JS. In addition, TypeScript adds more types, such as any type.

'any' is a loose TypeScript type This means that this variable can be of any type: string, Boolean, object, etc In fact, it's like there's no type check at all.

Behavior in TypeScript

Let's start with a legal KS function: filterByTerm. Create a new file called filterByTerm.js in the project folder and enter the following

function filterByTerm(input, searchTerm) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

filterByTerm("input string", "java");

If you don't understand logic now, don't worry Take a look at the parameters of the function and how to use them after a few lines. Just look at the code and you should have found the problem.

I wonder if there's a way to check this function in my IDE without running code or using Jest Test it. Is this possible? TypeScript does a good job in this area, in fact it is the best tool for static checking in JS, that is, testing the correctness of the code before it runs.

Therefore, we use TypeScript instead, changing the extension of the file from filterByTerm.js to filterByTerm.ts. With this change, you'll find a bunch of errors in the code

You can see that there are many red marks under the function parameters. From now on, we'll show you errors in the form of text, but remember that the IDE and the text editor will show these red lines when we make errors in TypeScript.

Determine what's wrong:

npm run tsc

You can see the error report of the control:

filterByTerm.ts:1:23 - error TS7006: Parameter 'input' implicitly has an 'any' type.

1 function filterByTerm(input, searchTerm) {
                        ~~~~~

filterByTerm.ts:1:30 - error TS7006: Parameter 'searchTerm' implicitly has an 'any' type.

1 function filterByTerm(input, searchTerm) {
                               ~~~~~~~~~~

filterByTerm.ts:5:32 - error TS7006: Parameter 'arrayElement' implicitly has an 'any' type.

5   return input.filter(function(arrayElement) {

TypeScript tells you that a function parameter has the type "any", which can be any in TypeScript if you remember We need to add appropriate type comments to our TypeScript code.

What is the type? What are the problems in JS

So far, there are seven types of JS

  • String
  • Number
  • Boolean
  • Null
  • Undefined
  • Object
  • Symbol (ES6)

In addition to the Object type, other basic data types of JS. Each JS type has a corresponding representation, which can be used in code, such as string and number

var name = "Hello John";
var age = 33;

The problem with JS is that variables can change their type at any time. For example, a Boolean value can become a string (save the following code in a file called types.js)

var aBoolean = false;
console.log(typeof aBoolean); // "boolean"

aBoolean = "Tom";
console.log(typeof aBoolean); // "string"

The transformation can be intentional, and developers may really want to assign Tom to a boolean, but such errors are likely to happen by accident.

Technically, JS itself has no problem because its type dynamics are intentional. JS was born as a simple web scripting language, not as a mature enterprise language.

However, the loose nature of JS can cause serious problems in your code and damage its maintainability. TypeScript is designed to solve these problems by adding strong types to JS. In fact, if you change the extension of types.js to types.ts. You'll see TypeScript complaints in the IDE.

The compilation console of types.ts will report an error:

types.ts:4:1 - error TS2322: Type '"Tom"' is not assignable to type 'boolean'.

With this knowledge, let's take a deeper look at TypeScript types.

Drill down on TypeScript types

TypeScript emphasizes that there are types. The code above has no types at all. It's time to add some. First, you need to correct the function parameters. By observing how this function is called, it appears to take two strings as parameters:

filterByTerm("input string", "java");

Add type for parameter:

function filterByTerm(input: string, searchTerm: string) {
    // ...
}

// ...

Then compile:

npm run tsc

Remaining errors:

filterByTerm.ts:5:16 - error TS2339: Property 'filter' does not exist on type 'string'.

You can see how TypeScript guides us. The problem now is the filter method.

function filterByTerm(input: string, searchTerm: string) {
  // Omit some
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

Let's tell TypeScript that "input" is a string, but in the latter code, the filter method is called. It belongs to an array. What we really need is to mark the input as an array of something, maybe an array of strings:

There are two options for this. Option 1: string []

function filterByTerm(input: string[], searchTerm: string) {
    // ...
}

Option 2: array < type >

function filterByTerm(input: Array<string>, searchTerm: string) {
    // ...

}

I personally prefer option 2 Now, try to compile (npm run tsc) again. The console information is as follows:

filterByTerm.ts:10:14 - error TS2345: Argument of type '"input string"' is not assignable to parameter of type 'string[]'.

filterByTerm("input string", "java");

TypeScript also verifies the type passed in Let's change the input to an array of strings:

filterByTerm(["string1", "string2", "string3"], "java");

This is the complete code so far:

function filterByTerm(input: Array<string>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

filterByTerm(["string1", "string2", "string3"], "java");

It looks good, but npm run tsc still can't pass:

filterByTerm.ts:6:25 - error TS2339: Property 'url' does not exist on type 'string'.

TypeScript is really rigorous We passed in an array of strings, but after the code, we tried to access a property called "url":

return arrayElement.url.match(regex);

This means we need an array of objects, not strings. Let's solve the problem in the next section.

TypeScript objects and interfaces

There is a problem left over: because filterByTerm is passed an array of strings. The url property does not exist on TypeScript of type string. So let's instead pass an array of objects to solve this problem:

filterByTerm(
  [{ url: "string1" }, { url: "string2" }, { url: "string3" }],
  "java"
);

The function definition should also be changed accordingly:

function filterByTerm(input: Array<object>, searchTerm: string) {
    // omitted
}

Now let's compile the code

npm run tsc

Control output:

filterByTerm.ts:6:25 - error TS2339: Property 'url' does not exist on type 'object'.

Again, the generic JS object does not have any properties named url. For me, TypeScript is really strict with type requirements.

The problem here is that we can't assign properties to a random object. One of the core principles of TypeScript is to check the structure of values. In TypeScript, the function of interface is to name these types and define contracts for your code or third-party code. We can use interface to solve this problem.

By looking at our code, we can think of a simple "model" called Link, whose structure should conform to the following pattern: it must have a url attribute of type string.

In TypeScript, you can define the model with an interface, like this (put the following code at the top of filterByTerm.ts):

interface ILink {
  url: string;
}

For interface declarations, this is certainly not a valid JS syntax and will be removed during compilation.

Tip: it is the Convention of TypeScript to prefix the interface name with an uppercase I.

Now, define the input type using the interface ILink

function filterByTerm(input: Array<ILink>, searchTerm: string) {
    // ...
}

Through this repair, it can be said that TypeScript "expects the ILink array" as the input of this function. The following is the complete code:

interface ILink {
  url: string;
}

function filterByTerm(input: Array<ILink>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

filterByTerm(
  [{ url: "string1" }, { url: "string2" }, { url: "string3" }],
  "java"
);

At this point, all the errors should be gone, and you can run:

npm run tsc

After compilation, a file named filterByTerm.js is generated in the project folder, which contains pure JS code. You can check out the file and see what the TypeScript specific declaration is ultimately converted to JS.

Because alwaysStrict is set to true, the TypeScript compiler also uses use strict at the top of filterByTerm.js.

Interfaces and fields

The TypeScript interface is one of the most powerful structures in the language. Interfaces help to model the entire application so that any developer can choose this model and follow it when writing code.

Previously, we defined a simple interface, ILink

interface ILink {
  url: string;
}

If you want to add more fields to the interface, simply declare them in the block:

interface ILink {
  description: string;
  id: number;
  url: string;
}

Now, all objects of type ILink must implement new fields, otherwise an error will occur. If you write the above definition to filterByTerm.ts and recompile it, an error will be reported:

filterByTerm.ts:17:4 - error TS2739: Type '{ url: string; }' is missing the following properties from type 'ILink': description, id

The problem is the parameters of our function:

filterByTerm(
  [{ url: "string1" }, { url: "string2" }, { url: "string3" }],
  "java"
);

TypeScript can infer from function declaration that the parameter is an array of types of ILink. Therefore, any object in the array must implement all fields defined in the interface ILink

In most cases, it is not realistic to implement all fields. After all, we don't know if every new object of type ILink will need to have all the fields. However, don't worry. To make the compilation pass, you can declare that the fields of the interface are optional. Use? To indicate:

interface ILink {
  description?: string;
  id?: number;
  url: string;
}

Now the editor and compiler are fine. However, TypeScript interfaces can do more, and we'll see how to extend them in the next section. But let's start with a brief introduction to variables in TypeScript.

Variable declaration

So far, we've learned how to add types to function parameters:

function filterByTerm(input: Array<ILink>, searchTerm: string) {
    //
}

TypeScript is not limited to this, but you can also add a type to any variable. To illustrate this example, let's extract the parameters of the function one by one. First, we need to extract each individual object:

const obj1: ILink = { url: "string1" };
const obj2: ILink = { url: "string2" };
const obj3: ILink = { url: "string3" };

Next, we can define an ILink array like this:

const arrOfLinks: Array<ILink> = [obj1, obj2, obj3];

The type corresponding to the parameter searchTerm can be as follows:

const term: string = "java";

Here is the complete code:

interface ILink {
  description?: string;
  id?: number;
  url: string;
}

function filterByTerm(input: Array<ILink>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

const obj1: ILink = { url: "string1" };
const obj2: ILink = { url: "string2" };
const obj3: ILink = { url: "string3" };

const arrOfLinks: Array<ILink> = [obj1, obj2, obj3];

const term: string = "java";

filterByTerm(arrOfLinks, term);

TypeScript looks verbose and sometimes redundant compared to JS. But over time, you'll find that the more types you add, the more robust your code will be.

By adding type comments, you can learn more about TypeScript and help you better understand the intent of your code.

For example, arrOfLinks is associated with the correct type (array of ILink). Our editor can infer that every object in the array has an attribute named url, as defined in the interface ILink:

TypeScript has more types than strings, arrays, and numbers. There are boolean, tuple, any, never, enum. If you're interested, you can View documents.

Now, let's continue to expand the interface.

Extended interface

The TypeScript interface is good. However, if we need a new object one day, the type we need is almost the same as the interface we have now. Suppose we need a new interface called IPost with the following properties:

  • id, number
  • title, string
  • body, string
  • url, string
  • description, string

Some of the fields in this interface are available in our ILink interface.

interface ILink {
  description?: string;
  id?: number;
  url: string;
}

Is there any way to reuse the interface ILink? In TypeScript, you can use inheritance to extend the interface. The keywords are represented by extensions:

interface ILink {
  description?: string;
  id?: number;
  url: string;
}

interface IPost extends ILink {
  title: string;
  body: string;
}

Now, objects of type IPost will have optional attributes description, id, url and mandatory attributes title and body:

interface ILink {
  description?: string;
  id?: number;
  url: string;
}

interface IPost extends ILink {
  title: string;
  body: string;
}

const post1: IPost = {
  description:
    "TypeScript tutorial for beginners is a tutorial for all the JavaScript developers ...",
  id: 1,
  url: "www.valentinog.com/typescript/",
  title: "TypeScript tutorial for beginners",
  body: "Some stuff here!"
};

When an object like post1 uses an interface, we say that post1 implements the properties defined in that interface.

Extending interfaces means borrowing their properties and extending them for code reuse. Of course, the TypeScript interface can also describe functions, as you will see later.

Indexes

JS objects are containers for key / value pairs Here is a simple object:

const paolo = {
  name: "Paolo",
  city: "Siena",
  age: 44
};

We can access the value of any key using point syntax:

console.log(paolo.city);

Now, assuming that the key is dynamic, we can put it in a variable and reference it in parentheses

const paolo = {
  name: "Paolo",
  city: "Siena",
  age: 44
};

const key = "city";

console.log(paolo[key]);

Now let's add another object, put them all in an array, and use the filter method to filter the array, as we did in filterByTerm.js. But this time the key is passed dynamically, so you can filter any object key:

const paolo = {
  name: "Paolo",
  city: "Siena",
  age: 44
};

const tom = {
  name: "Tom",
  city: "Munich",
  age: 33
};

function filterPerson(arr, term, key) {
  return arr.filter(function(person) {
    return person[key].match(term);
  });
}

filterPerson([paolo, tom], "Siena", "city");

This is an important line:

return person[key].match(term);

Yes, because JS doesn't care whether paolo or tom can be "indexed" through dynamic [key] What about TS?

In the next section, we'll use dynamic keys to make filterByTerm more flexible.

Interfaces can have indexes

Let's go back to the filterByTerm function in filterByTerm.ts

function filterByTerm(input: Array<ILink>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

It doesn't look so flexible, because for every ILink, we use hard coding to match the attribute url to the regular expression. We want to make dynamic properties (that is, keys) more flexible:

function filterByTerm(
  input: Array<ILink>,
  searchTerm: string,
  lookupKey: string = "url"
) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement[lookupKey].match(regex);
  });
}

lookupKey Is a dynamic key, which is assigned a default parameter "url". Then compile the code:

npm run tsc

Of course, an error will be reported:

error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'ILink'.
  No index signature with a parameter of type 'string' was found on type 'ILink'.

Error line:

return arrayElement[lookupKey].match(regex);

The element implicitly has the type "any", because the type "ILink" has no index signature, so you need to add an interface to index to the object, which is easy to solve.

Go to interface ILink and add index:

interface ILink {
  description?: string;
  id?: number;
  url: string;
  [index: string] : string
}

The syntax is a bit strange, but it's similar to dynamic key access on objects. This means that we can access any key of the object through an index of type string, which in turn returns another string.

However, this will cause other errors:

error TS2411: Property 'description' of type 'string | undefined' is not assignable to string index type 'string'.
error TS2411: Property 'id' of type 'number | undefined' is not assignable to string index type 'string'.

This is because some properties on the interface are optional, possibly undefined, and the return type is not always string (for example, id is a number).

interface ILink {
  description?: string;
  id?: number;
  url: string;
  [index: string]: string | number | undefined;
}

This line:

[index: string]: string | number | undefined;

Indicates that the index is a string and can return another string, number, or undefined. Try compiling again, there is another error

error TS2339: Property 'match' does not exist on type 'string | number'.
return arrayElement[lookupKey].match(regex);

There's nothing wrong with the report. match Method only exists in the string, and our index might return a number. To fix this, we can use any type:

interface ILink {
  description?: string;
  id?: number;
  url: string;
  [index: string]: any;
}

Compile again.

Return type of function

So far, there are many new things. Now let's look at another useful feature of TypeScript: the return type of the function.

Return to the filterByTerm function:

function filterByTerm(
  input: Array<ILink>,
  searchTerm: string,
  lookupKey: string = "url"
) {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement[lookupKey].match(regex);
  });
}

If you call as is, passing the ILink array and the search term string3 you saw earlier, an array of objects will be returned as expected:

filterByTerm(arrOfLinks, "string3"); 

// EXPECTED OUTPUT:
// [ { url: 'string3' } ]

But now consider a variation of the change:

function filterByTerm(
  input: Array<ILink>,
  searchTerm: string,
  lookupKey: string = "url"
) {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  if (!input.length) throw Error("input cannot be empty");
  const regex = new RegExp(searchTerm, "i");
  return input
    .filter(function(arrayElement) {
      return arrayElement[lookupKey].match(regex);
    })
    .toString();
}

If called now, using the same ILink array and search term string3, it will return [object]

filterByTerm(arrOfLinks, "string3");

// WRONG OUTPUT:
// [object Object]

This function doesn't work as expected, and it's hard to find problems if you don't know about JS implicit type conversion. Fortunately, TypeScript can catch these errors, as you write in the editor.

Amend to read:

function filterByTerm(/* ellipsis */): Array<ILink> {
 /* ellipsis */
}

How does it work? Tell TypeScript to expect another array as a return value by adding a type comment before the function body. Now the bug is easy to find.

interface ILink {
  description?: string;
  id?: number;
  url: string;
  [index: string]: any;
}

function filterByTerm(
  input: Array<ILink>,
  searchTerm: string,
  lookupKey: string = "url"
): Array<ILink> {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  if (!input.length) throw Error("input cannot be empty");
  const regex = new RegExp(searchTerm, "i");
  return input
    .filter(function(arrayElement) {
      return arrayElement[lookupKey].match(regex);
    })
    .toString();
}

const obj1: ILink = { url: "string1" };
const obj2: ILink = { url: "string2" };
const obj3: ILink = { url: "string3" };

const arrOfLinks: Array<ILink> = [obj1, obj2, obj3];

filterByTerm(arrOfLinks, "string3");

Now compile and check for errors:

error TS2322: Type 'string' is not assignable to type 'ILink[]'.

We want to return an ILink array instead of a string. To fix this, remove. tostring() from the end and recompile the code.

Type alias vs interface

So far, we've seen interfaces as tools for describing objects and custom types. But with other people's code, you may have noticed the type of the keyword as well.

Obviously, interface and type can be used interchangeably in TypeScript, but they are different in many ways, which is the confusion of TypeScript for beginners.

Remember: the interface description in TypeScript is the structure of something, mostly a complex object.

Type, on the other hand, can also be used to describe a custom structure, but it's just an alias, or in other words, a label for a custom type. For example, imagine an interface with two fields, one of which is a union type of Boolean, numeric, and string.

interface IExample {
  authenticated: boolean | number | string;
  name: string;
}

For example, using the type alias can extract a custom union type and create a label named Authenticated

type Authenticated = boolean | number | string;

interface IExample {
  authenticated: Authenticated;
  name: string;
}

In this way, I can isolate the changes I have made without having to copy / paste union types throughout the code base.

If you want to apply type to the above example (filterByTerm), create a new label called ILinks and assign array < ilink > to it In this way, you can refer to the former:

// the new label
type ILinks = Array<ILink>;
// the new label

function filterByTerm(
  input: ILinks,
  searchTerm: string,
  lookupKey: string = "url"
): ILinks {
  if (!searchTerm) throw Error("searchTerm Can not be empty");
  if (!input.length) throw Error("input Can not be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement[lookupKey].match(regex);
  });
}

const obj1: ILink = { url: "string1" };
const obj2: ILink = { url: "string2" };
const obj3: ILink = { url: "string3" };

const arrOfLinks: ILinks = [obj1, obj2, obj3];

filterByTerm(arrOfLinks, "string3");

Of course, this is not the best example of type usage. Which one should I use between interface and type? I prefer the interface of complex objects. TypeScript document Also suggested.

The ideal state for a software is extensible, so always use interfaces on type aliases, if possible.

More about interfaces and objects

Functions are first-class citizens in JS, and objects are the most important entities in the language.

It's no surprise that objects are mostly containers of key / value pairs, which can also hold functions. When a function is inside an object, it can access the "host" object through the keyword this:

const tom = {
  name: "Front-end little intelligence",
  city: "Xiamen",
  age: 26,
  printDetails: function() {
    console.log(`${this.name} - ${this.city}`);
  }
};

So far, we've seen TypeScript interfaces applied to simple objects to describe strings and numbers But they can do more For example, create a new file called interfaces-functions.ts using the following code:

const tom = {
  name: "Front-end little intelligence",
  city: "Xiamen",
  age: 26,
  printDetails: function() {
    console.log(`${this.name} - ${this.city}`);
  }
};

This is a JS object. Let's use the interface IPerson to add the type to it:

interface IPerson {
  name: string;
  city: string;
  age: number;
}

const tom: IPerson = {
  name: "Front-end little intelligence",
  city: "Xiamen",
  age: 26,
  printDetails: function() {
    console.log(`${this.name} - ${this.city}`);
  }
};

Compile the code and view the error message:

interfaces-functions.ts:11:3 - error TS2322: Type '{ name: string; city: string; age: number; printDetails: () => void; }' is not assignable to type 'IPerson'.
  Object literal may only specify known properties, and 'printDetails' does not exist in type 'IPerson'.

IPerson does not have any properties called printDetails, but more importantly it should be a function. Fortunately, the TypeScript interface can also describe functions. As follows:

interface IPerson {
  name: string;
  city: string;
  age: number;
  printDetails(): void;
}

Here, we add the property printDetails of the type function to return void Void means no value is returned.

In fact, functions printed to the console do not return anything If you want to return a string from printDetails, you can adjust the return type to string:

interface IPerson {
  name: string;
  city: string;
  age: number;
  printDetails(): string;
}

const tom: IPerson = {
  name: "Front-end little intelligence",
  city: "Xiamen",
  age: 26,
  printDetails: function() {
    return `${this.name} - ${this.city}`;
  }
};

What if functions have parameters? In the interface, you can add type comments for them

interface IPerson {
  name: string;
  city: string;
  age: number;
  printDetails(): string;
  anotherFunc(a: number, b: number): number;
}

The bugs that may exist after code deployment can't be known in real time. In order to solve these bugs afterwards, a lot of time has been spent on log debugging. Here is a good BUG monitoring tool recommended by the way Fundebug.

Original text: https://www.valentinog.com/bl...

summary

You cannot cover every TypeScript feature here. For example, omitted [ES2015 class and its interface with or higher-level type]6 Relationship. Of course, we will continue to introduce it later.

In this TypeScript tutorial, I talked about:

  • Type comments for variables, function parameters, and return values
  • Interface
  • Custom type
  • Type alias

    TS helps us reduce some JS code hidden errors. You need to repeat that TypeScript cannot replace a test Clam is a valuable tool. It's hard to master at first, but it's worth investing in.

Communication

Alibaba cloud has been doing activities recently, with a discount of 20%. If you are interested, please take a look at: https://promotion.aliyun.com/...

The articles of dry goods series are summarized as follows. I think it's a good idea to order a Star. Welcome to learn from each other.

https://github.com/qq449245884/xiaozhi

Because of the space limitation, today's sharing is only here. If you want to know more about it, you can scan the bottom two dimensional code of each article, then pay attention to our WeChat public address, and learn more information and valuable content.

I don't go to bed until 2 o'clock every time I sort out the articles. It's very painful. I hope I can support you and encourage you

Topics: Javascript TypeScript npm Java JSON