Type annotations in functions

The function can specify the type of each argument and return value:

function add(x: number, y: number) :number {
  return x + y;
}

let myAdd = function (x: number, y: number) :number {
  return x + y;
};
Copy the code

When you omit a type annotation for a returned value, Typescript automatically makes type inferences based on the returned value.

Function types

As with other variables, you can annotate a variable as a function type in the format (a: number, b:number) => number as follows:

let myAdd: (x: number, y: number) = > number = function (
  x: number,
  y: number
) :number {
  return x + y;
};
Copy the code

Note that x and y are placeholders and can be named as anything

Type inference

You can only write type annotations on one side of the equation, and Typescript automatically does type inference on the other side based on the locale:

// The parameters 'x' and 'y' have the type number
let myAdd = function (x: number, y: number) :number {
  return x + y;
};

// myAdd has the full function type
let myAdd2: (baseValue: number, increment: number) = > number = function (x, y) {
  return x + y;
};
Copy the code

Optional and default parameters

Arguments to functions in Typescript are mandatory by default, so the number of arguments passed in a function call must be the same as when declared:

function buildName(firstName: string, lastName: string) {
  return firstName + "" + lastName;
}

let result1 = buildName("Bob"); // error, too few parameters
Expected 2 arguments, but got 1.
let result2 = buildName("Bob"."Adams"."Sr."); // error, too many parameters
Expected 2 arguments, but got 3.
let result3 = buildName("Bob"."Adams"); // ah, just right
Copy the code

In JavaScript, each parameter to a function is optional and can be passed by the user as the case may be. In TypeScript, to make an argument optional, you can change the type annotation to? : :

function buildName(firstName: string, lastName? :string) {
  if (lastName) return firstName + "" + lastName;
  else return firstName;
}

let result1 = buildName("Bob"); // works correctly now
let result2 = buildName("Bob"."Adams"."Sr."); // error, too many parameters
Expected 1-2 arguments, but got 3.
let result3 = buildName("Bob"."Adams"); // ah, just right
Copy the code

Note that optional parameters need to be followed by required parameters. Alternatively, we can provide a default value for a parameter and use it when the user does not pass or pass undefined:

function buildName(firstName: string, lastName = "Smith") {
  return firstName + "" + lastName;
}

let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"
let result2 = buildName("Bob".undefined); // still works, also returns "Bob Smith"
let result3 = buildName("Bob"."Adams"."Sr."); // error, too many parameters
Expected 1-2 arguments, but got 3.
let result4 = buildName("Bob"."Adams"); // ah, just right
Copy the code

The optional argument followed by the required argument can be considered equivalent to the default argument:

function buildName(firstName: string, lastName? :string) {
  // ...
}
Copy the code

Is equal to:

function buildName(firstName: string, lastName = "Smith") {
  // ...
}
Copy the code

Unlike optional parameters, default parameters can appear before required parameters. In this case, the default values for undefiend must be used.

function buildName(firstName = "Will", lastName: string) {
  return firstName + "" + lastName;
}

let result1 = buildName("Bob"); // error, too few parameters
Expected 2 arguments, but got 1.
let result2 = buildName("Bob"."Adams"."Sr."); // error, too many parameters
Expected 2 arguments, but got 3.
let result3 = buildName("Bob"."Adams"); // okay and returns "Bob Adams"
let result4 = buildName(undefined."Adams"); // okay and returns "Will Adams"
Copy the code

The remaining parameters

Similar to the remaining parameters in ES6, use… Represents the remaining arguments, which can be seen as putting all the optional arguments into an array:

function buildName(firstName: string. restOfName:string[]) {
  return firstName + "" + restOfName.join("");
}

// employeeName will be "Joseph Samuel Lucas MacKinzie"
let employeeName = buildName("Joseph"."Samuel"."Lucas"."MacKinzie");
Copy the code

Support for function type annotations and declarations:

function buildName(firstName: string. restOfName:string[]) {
  return firstName + "" + restOfName.join("");
}

let buildNameFun: (fname: string. rest:string[]) = > string = buildName;
Copy the code

Function overloading

Some functions can have multiple parameter types, and return types can be indeterminate:

let suits = ["hearts"."spades"."clubs"."diamonds"];

function pickCard(x: any) :any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13}; }}let myDeck = [
  { suit: "diamonds".card: 2 },
  { suit: "spades".card: 10 },
  { suit: "hearts".card: 4},];let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
Copy the code

The above function returns a number if an object is passed in. If a number is passed, the card object is returned. How exactly do you describe these different parameter types in TypeScript? That is function overloading, which allows us to define a range of parameter type annotations in different cases and generally declare them in the order from specific to most obscure:

let suits = ["hearts"."spades"."clubs"."diamonds"];

function pickCard(x: { suit: string; card: number} []) :number;
function pickCard(x: number) :{ suit: string; card: number };
function pickCard(x: any) :any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13}; }}let myDeck = [
  { suit: "diamonds".card: 2 },
  { suit: "spades".card: 10 },
  { suit: "hearts".card: 4},];let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
Copy the code

When a function is called, TypeScript matches the type from the first in the overloaded function list, and if the argument matches, it checks the type against that declaration.

Note that the last declaration of the function overload list does not do type matching, so the list above will throw an exception if the arguments do not match the previous two minutes