Web-Typescript interface

interface

        Typescript interfaces serve a similar purpose to the interfaces you are used to in C# and Java, but they have very different semantics. In C# and Java, interfaces are primarily used as templates for classes that implement the interface. Typescript classes can also be used for this purpose, but they can also be thought of as templates for JavaScript objects.

        Suppose we declare the following JavaScript object using automatic type inference.

let me = { name:"Reza", age:21, address:"Gold Coast" };

        We can declare three simple Typescript interfaces to match this (and more are possible).

 interface Person1 { name:string; age: number;  address:string; } ;
 interface Person2 { name:string;  age: number; } ;
 interface Person3 { name:string; } ; 

        Please note the use of semicolon ';' (it is not a comma) and there is a semicolon after the last attribute.

        These three interfaces can be used in the original object declaration as shown below.

let me1 : Person1 = { name:"Reza", age:21, address:"Gold Coast" };
let me2 : Person2 = { name:"Reza", age:21 };
let me3 : Person3 = { name:"Reza" };

        They have different type checking implications. The first one will insist that all three properties are present in the initialized object. The second declaration will only persist two properties, and the third declaration will only persist one property. This means that the following declaration will fail Typescript checking.

  let me1 : Person1 = { name:"Reza", age:21 };
  let me2 : Person2 = { name:"Reza", age:21, hieght:92.5};
  let me3 : Person3 = { name:"Reza", hieght:123};

        The reasons for this set of TypeScript code errors are as follows:

  1. In the first line of code, the variable  me1 is defined as type  Person1, but it is missing  Person1 the properties defined in  the interface address.
  2. In the second line of code, the variable  me2 is defined as a type  Person2, but it contains an extra property  hieght, which  Person2 is not defined by the interface.
  3. In the third line of code, the variable  me3 is defined as a type  Person3, but it is missing  Person3 the properties defined in  the interface hieght.

        In each of the above cases, one of the interface members does not exist, or there are extra elements in the object used to initialize the variable.

        Although the way interfaces are used in object initialization is strict, this changes when interfaces are used as function parameters. This behavior is similar to polymorphic behavior in C# or Java. Consider the following function definition, which uses the Person3 interface above to define parameters:

let pname = function(n:Person3):string {
    return n.name;
  }

        The following calls are all correct:

console.log(pname(me1));
console.log(pname(me2));
console.log(pname(me3));

        Typescript objects also allow us to specify optional properties. This has similar syntax to the optional parameters we saw in the previous section. The following variation of the above interface example allows the age and address attributes to be optional.

interface Person4 { name:string; age?: number; address?:string; } ;
let me4:Person4 = { name: "Reza"}; // OK
let me5:Person4 = { name: "Reza", age:21}; // OK

        Typescript objects also allow us to specify optional properties. This has similar syntax to the optional parameters we saw in the previous section. The following variation of the above interface example allows the age and address attributes to be optional.

interface Person4 { name:string; age?: number; address?:string; } ;
let me4:Person4 = { name: "Reza"}; // OK
let me5:Person4 = { name: "Reza", age:21}; // OK

        To determine whether an optional attribute is provided, we can use an if statement. For example, the following function checks whether the age and address attributes exist and inserts a value if they do not exist.

function fillPerson (p:Person4): Person1 {
    let newp:Person1 =
      {name: "", age:10, address: "No fixed address"};
    newp.name = p.name;
    if (p.age) { // optional property present
      newp.age=p.age;
    }
    if (p.address) { // optional property present
      newp.address=p.address;
    }
    return newp;
  }

        Another feature of interfaces is that we can designate members as read-only. As with variables, this means that interface properties can only be updated when an object with the interface is initialized, and Typescript will display an error any other time.

        For example, we can make the name property read-only in the following example:

  interface Person5 { readonly name:string; age?: number; address?:string; } ;

        For any object declared as having interface Person5, attempting to change the name property will result in a Typescript syntax error.

        We can also declare functional interfaces and array interfaces. These are not exactly the same as what we have seen so far, as they usually only work with a single function or a single array (as opposed to an object with multiple properties). You can think of these as a way of assigning a name to a function type or array type.

        Below is a simple example of a functional interface declaration.

        This will correctly type check using any function that takes two numeric arguments and returns a number. Note that the parameter names in the interface do not have to match the names in the actual function definition, the same goes for the function types we saw earlier.

        Indexable type interfaces (such as arrays) can also be defined similarly. For example, the following interface declaration will correctly type check against any array of numbers (indexed numerically).

 interface NumArray {
    [index:number]: number;
  } 

        Note that indexable types can also be indexed by other types (e.g. by strings). For example, the following types are arrays of numbers indexable by strings:

 interface NumArray2 {
    [index:string]: number;
  } 

        For this array, we can index by any string (very different from C# or Java), for example:

  let a1:NumArray2 = {};
  a1["hippo"] = 23;
  console.log(a1["hippo"]);

        Typescript classes can implement interfaces just like other languages. We'll wait until we look at the class to demonstrate.

        Finally, interfaces can also use inheritance, just like you've seen in other languages. For example, we can declare an interface called Animal and extend it to the Pet interface that contains all the properties of Animal.

interface Animal {
    species: string;
  }
  interface Pet extends Animal {
    name: string;    // the species property is inherited to be part of this
  }

        As mentioned before, the Typescript interface is the same as C# or Java, but there are some additional applications in Typescript. You will become familiar with interfaces when used with classes. In Typescript, they are also used with JavaScript objects.

        Consider the following Typescript interface definition:

  interface Student {ID:number; name: string; marks: number};

        Notice how the various parts of the interface are separated by semicolons ";" instead of the commas "," used with JavaScript objects.

        We can leverage this interface to define variables so that Typescript will check if the object has the correct form. For example, the following object variables have correct and incorrect initialization:

  let s1:Student = {ID:1234, name: "Baz", marks: -1};
  let s2:Student = {ID:1234, name: "Baz" }; // error 'marks' is missing

        An interface type declaration only checks the specified elements and cannot add additional elements like interfaces in other languages. For example, the following is incorrect:

 interface Student2 {ID:number};
 let s3:Student2 = {ID:1234, name: "Baz", marks: -1}; // fails 

This strict behavior is not reflected         when we use the function parameter interface . Your author thinks this is not very consistent. Consider the following functions using the above interface:

let getID = function (s:Student2) {
    return s.ID;
  }

        Now, looking at the definition of Student2, we expected the following to fail, but they are correct.

        In both cases, the function parameter only requires an object with an ID property. Note that S6 doesn't even use interfaces to define objects. This contrasts with the rigorous inspection of literal objects explained above.

        We can also use interfaces to prevent changes to object properties. This is achieved through the read-only keyword. For example, we can make the StudentID property read-only so that Typescript will generate a syntax error if we try to change it:

interface Student3 {
  readonly ID:number;
  name: string;
  marks: number
  };

        To allow optional elements in interfaces, there is a specific syntax. Suppose we want to make the Name and Tag properties in the above Student interface optional. We specify it with the "?" symbol after the identifier:

interface Student4 {ID:number; name?:string; marks?: number;};

        We can then assign as follows:

 let s7:Student4 = {ID:1234, name: "Baz"};
 let s8:Student4 = {ID:1234, marks: 23};
 let s9:Student4 = {ID:1234}; 

        We can also declare functional interfaces and array interfaces. These are different from the ones we've seen so far. They usually only work with a single function or a single array (not objects with multiple properties). You can think of these as a way

        Specify a name for a function type or array type.

        Below is a simple example of a functional interface declaration.

interface BinNumFun {
    (n1:number, n2:number): number;
  }

        This will correctly type check using any function that takes two numeric arguments and returns a number. Note that the parameter names in the interface do not have to match the names in the actual function definition, the same goes for the function types we saw earlier. So to use this function type we just use the symbol BinNumFun.

        Indexable type interfaces (such as arrays) can also be defined similarly. For example, the following interface declaration will correctly type check against any array of numbers (indexed numerically).

interface NumArray {
    [index:number]: number;
  }

        Note that indexable types can also be indexed by other types (e.g. by strings). For example, the following types are arrays of numbers indexable by strings:

interface NumArray2 {
    [index:string]: number;
  }

        For this array we can index by any string (very different from C# or Java), e.g.

let a1:NumArray2 = {};
  a1["hippo"] = 23;
  console.log(a1["hippo"]);

        Typescript classes can implement interfaces just like other languages. We'll wait until we look at the class to demonstrate. Interfaces can also use inheritance as seen before.

Guess you like

Origin blog.csdn.net/qq_54813250/article/details/133578966