Function signing and function overloading

functionThe signature

Also called type signatures, or method signatures, define the inputs and outputs of a function or method

  • Parameter and parameter type
  • Return value and its type
  • Exceptions that may be thrown or returned

The function definitions

  • Review the two main ways to define functions in javaScript
// Function declaration
function add(x, y) {
    return x + y;
}

// Function expressions: assign an anonymous function to a variable
let myAdd = function(x, y) { return x + y; };

Copy the code
  • Add a type to the input parameter and return value of a JS function
function add(x: number, y: number) :number {
    return x + y;
}

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

Function types

  • A complete function type: contains only two parts, the parameter type and the return value type
  • The name of a parameter type and the name of a function parameter can be inconsistent, written consistent to increase readability of the function type.
  • When a type is specified on one side but not on the other, the TypeScript compiler automatically recognizes the type through type inference.
let myAdd = (x: number, y: number) = > number = function(x: number, y: number) :number { return x + y; };
Copy the code

Type Interface Type Interface

  • Interfaces can also be used to standardize the shape of functions
  • The function definition that needs to list the return value type of the parameter list in Interface. It is written as follows:
    • Defines a function interface
    • The types of arguments and return values accepted by the convention
    • Use function expressions to define functions of this shape
interface SearchFunc {
  (source: string, subString: string): boolean;
}
let mySearch: SearchFunc = function(source: string, subString: string) :boolean {
  let result = source.search(subString);
  return result > -1;
}

// Allow no type to be specified, TypeScrit will infer
let mySearch: SearchFunc = function (src, sub) {
    let result = src.search(sub);
    return result > -1;
}

Copy the code

For interfaces that have only one function, we can use type to define the type of a function:

Type alias Type Aliases

  • A type alias gives a type a new name.
  • Type aliases are sometimes similar to interfaces, but can work with primitive values, union types, tuples, and any other type you need to write by hand
  • Aliasing does not create a new type – it creates a new name to refer to that type.
  • Aliasing primitive types is usually useless, although it can be used as a form of documentation.
function greeter(fn: (a: string) => void) {
    fn("Hello, World");
}
function printToConsole(s: string) {
    console.log(s);
}
greeter(printToConsole);
Copy the code
type GreetFunction = (a: string) = > void;
function greeter(fn: GreetFunction) {
    // ...
}
Copy the code

Interface and Type

  • Type works and interface doesn’t
    • Type can declare basic type aliases, union types, tuples, and so on
// Base type alias
type Name = string

// Union type
interface Dog {
    wong();
}
interface Cat {
    miao();
}

type Pet = Dog | Cat

// Specify the type of each position in the array
type PetList = [Dog, Pet]
Copy the code

  • The type statement can also be assigned to the typeof the instance obtained using typeof
When you want to get the typeof a variable, use typeof

let div = document.createElement('div');
type B = typeof div
Copy the code
  • Interface works and type doesn’t
interface User {
  name: string
  age: number
}

interface User {
  sex: string
}

/* User interface {name: string age: number sex: string} */
Copy the code

parameter

Optional parameters

  • The number of arguments passed to a function must match the number expected by the function, and the compiler checks that the user has passed in values for each argument.
  • For JS often encountered in a function call, the declaration of the entry parameter can be passed or not. We can use optional arguments

Optional arguments must be followed by required arguments

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
let result3 = buildName("Bob"."Adams");  // ah, just right
Copy the code

The default parameters

  • Default parameters are also optional
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
let result4 = buildName("Bob"."Adams");         // ah, just right
Copy the code

The remaining parameters

  • Converges the remaining arguments to a variable (the compiler creates an array of arguments). And can access the variable
function buildName(firstName: string, ... restOfName: string[]) {
  return firstName + "" + restOfName.join("");
}

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

The return value

The return type of a function often returns any,nerver, or void in addition to the primitive type

any

never

  • neverA type represents a type that never has a value.
  • No type isneverCan be assigned to a subtype ofneverType, even thoughanyIt cannot be assigned tonever
// Return error
function error(message: string) :never {
    throw new Error(message);
}
// The inferred return value type is never
function fail() {
    return error("Something failed");
}

// A function that returns never must have an unreachable end
function infiniteLoop() :never {
    while (true) {}}Copy the code

void

  • In a way,voidType image is associated withanyType, on the other hand, means that there is no type. When a function does not return a value, you will usually see its return value of typevoid:
function warnUser() :void {
    console.log("This is my warning message");
}
Copy the code
  • Declare avoidA variable of type is not much use because you can only assign itundefinedandnull:
let unusable: void = undefined;
Copy the code

Function overloading

  • Function overloading: ** A subroutine with the same function item name ** but with different input and output types or numbers. It can simply be called the ability for a single function to perform multiple tasks.
  • TypeScript function overloading: provided for the same functionMultiple function type definitionsTo overload the function. The purpose is to overload the functionpickCardThe function is typed correctly when called.
  • Js does not need to support overloading because it is a dynamic type and can directly judge the type of parameters. However, TS supports type overloading of function signatures, namely multiple overload signatures and one implementation signatures, in order to ensure type safety
// Override the signature
function add(x:string,y:string) :string;
function add(x:number, y:number) :number;

	// The implementation signature is not visible to the public
function add(x:string|number, y: number|string) :number | string{
  if(typeof x === 'string') {return x + ', ' + y;
  }else {
    return x.toFixed() + (y as number).toFixed(); 
   Unfortunately, TS does not play a role of type narrowing for x but not for Y. Play a role of Type assert for Y manuallySee the HTTPS://github.com/Microsoft/TypeScript/issues/22609}}let x = add(1.2) // string
let y = add(2.3) // number
Copy the code

There are several caveats to implementing overloading

  • Because implementation signatures are not visible to the outside world, we usually need to define more than two overload signatures when we implement an overload
  • Implementation Signature and Overload signature must be compatible; otherwise, type check errors are generated
  • The overload signature type will not be merged and can only be resolved to one
function len(s: string) :number;
function len(arr: any[]) :number;
function len(x: any) {
  return x.length;
}

len(""); // OK
len([0]); // OK
let t = Math.random() > 0.5 ? "hello" : [0]
len(t); / / the t here is a string | number [] but still check the error
Copy the code

So instead of using overloading, let’s just use union type.

function len(x: any[] | string) {
  return x.length;
}
let t = Math.random() > 0.5 ? "hello" : [0]
len(t); // No problem
Copy the code

Compatibility of function types

The number of parameters of the target function must be greater than the number of parameters of the source function. The return value type of the target function must be the same as the return value type of the source function, or its subtype.