6

TypeScript 定义函数的几种写法

 3 years ago
source link: https://segmentfault.com/a/1190000040244082
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

写法1 - 使用 function 关键字

function greeter(fn: (a: string) => void) {
  fn("Hello, World");
}

function printToConsole(s: string) {
  console.log(s);
}

greeter(printToConsole);

(a: string) => void

上述语法的含义:表示一个函数,接收一个字符串作为输入参数,没有返回参数。

可以使用 type 关键字定义一个别名:

type GreetFunction = (a: string) => void;

Call signatures

使用 call signatures 给函数增加额外的属性。TypeScript 的 function 也是 value,和其他 value 一样。

注意:一定有 type 关键字。

type DescribableFunction = {
    description: string;
    (someArg: number): boolean;
  };
  
function doSomething(fn: DescribableFunction) {
    console.log(fn.description + " returned " + fn(6));
}

const fn = (a: number) => a > 10;

fn.description = 'Jerry';

另一种定义方式:

type DescribableFunction = {
    description: string;
    (someArg: number): boolean;
  };
const fn = <DescribableFunction>({
   description: 'Jerry'
});

const fn23 = Object.assign(
  function (number:number) { return number > 1 },
  fn
);
function doSomething(fn: DescribableFunction) {
    console.log(fn.description + " returned " + fn(6));
}

Construct signatures

type SomeConstructor = {
  new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
  return new ctor("hello");
}

Method Signatures

方法签名语法可能是最容易使用的。 在定义对象类型时,可以通过提供如下签名来轻松描述其方法:

interface Date {
  toString(): string;
  setTime(time: number): number;
  // ...
}

看个例子:

通过这种方式定义出来的函数,实际是一个 object:

如何实例化这种类型的 object?

const myDate = <MyDate>({
  toString: () => 'Jerry',
  setTime: (number) => number + 1
});

Function Type Literals

Function Type Literals 是另一种声明函数类型的方法。 它们通常用于高阶函数的签名,即接受函数作为参数或返回函数的函数:

interface Array<T> {
  sort(compareFn?: (a: T, b: T) => number): this;
  // ...
}

也许令人惊讶的是,在函数类型文字中总是需要参数名称。 您不能省略参数名称而只指定类型。

如果忘记指定形参名称,我们将无法得到期望的类型定义。下面的代码是一个例子:

我们本意想定义一个拥有两个输入参数,一个返回参数的函数类型,输入参数类型分别为 string 和 number.

type FunctionType2 = (string, number) => number;
// (string: any, number: any) => number

实际上,TypeScript 编译器将 string 和 number 理解成了形式参数名,且类型为 any. 这就和我们的期望不一致了。

总结一下:

Object Type Literals with Call or Construct Signatures

在 JavaScript 中,函数只不过是可以调用的特殊对象。 这个事实反映在对象类型文字的语法中:它们描述了对象的形状,它也恰好有一个调用签名:

interface RegExpConstructor {
  // Call signatures
  (pattern: RegExp): RegExp;
  (pattern: string, flags?: string): RegExp;

  // ...
}

与调用签名类似,对象类型文字也可以包含构造签名,在这种情况下,它被称为构造函数类型。 当使用 new 运算符调用函数时,函数的构造签名定义了它的参数列表和返回类型。 构造签名看起来与调用签名几乎相同,除了它们额外带有 new 关键字前缀:

interface RegExpConstructor {
  // Call signatures
  (pattern: RegExp): RegExp;
  (pattern: string, flags?: string): RegExp;

  // Construct signatures
  new (pattern: RegExp): RegExp;
  new (pattern: string, flags?: string): RegExp;

  // ...
}
// Using the call signature
const digitsPattern1 = RegExp("^\\d+$");

// Using the construct signature
const digitsPattern2 = new RegExp("^\\d+$");

更多Jerry的原创文章,尽在:"汪子熙":


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK