目前我有类型定义为:

interface Param {
    title: string;
    callback: any;
}

我需要这样的东西:

interface Param {
    title: string;
    callback: function;
}

但是第二项不被接受。


当前回答

Typescript:如何为方法参数中使用的函数回调定义类型?

你可以声明回调为1)函数属性或2)方法:

interface ParamFnProp {
    callback: (a: Animal) => void; // function property
}

interface ParamMethod {
    callback(a: Animal): void; // method
}

自TS 2.6以来,有一个重要的类型差异:

当声明函数属性时,在——strict或——strictFunctionTypes模式下可以获得更强的(“sound”)类型。让我们举个例子:

const animalCallback = (a: Animal): void => { } // Animal is the base type for Dog
const dogCallback = (d: Dog): void => { } 
// function property variant
const param11: ParamFnProp = { callback: dogCallback } // error: not assignable
const param12: ParamFnProp = { callback: animalCallback } // works

// method variant
const param2: ParamMethod = { callback: dogCallback } // now it works again ...

从技术上讲,在strictFunctionTypes下,方法是双变的,函数属性在参数中是逆变的。方法的检查仍然更加允许(即使不是sound),以便与内置类型(如Array)结合使用更实用。

总结

函数属性和方法声明之间存在类型差异 如果可能,为较强的类型选择函数属性

操场示例代码

其他回答

Typescript:如何为方法参数中使用的函数回调定义类型?

你可以声明回调为1)函数属性或2)方法:

interface ParamFnProp {
    callback: (a: Animal) => void; // function property
}

interface ParamMethod {
    callback(a: Animal): void; // method
}

自TS 2.6以来,有一个重要的类型差异:

当声明函数属性时,在——strict或——strictFunctionTypes模式下可以获得更强的(“sound”)类型。让我们举个例子:

const animalCallback = (a: Animal): void => { } // Animal is the base type for Dog
const dogCallback = (d: Dog): void => { } 
// function property variant
const param11: ParamFnProp = { callback: dogCallback } // error: not assignable
const param12: ParamFnProp = { callback: animalCallback } // works

// method variant
const param2: ParamMethod = { callback: dogCallback } // now it works again ...

从技术上讲,在strictFunctionTypes下,方法是双变的,函数属性在参数中是逆变的。方法的检查仍然更加允许(即使不是sound),以便与内置类型(如Array)结合使用更实用。

总结

函数属性和方法声明之间存在类型差异 如果可能,为较强的类型选择函数属性

操场示例代码

有四种抽象函数类型,当你知道你的函数是否接受参数,是否返回数据时,你可以分别使用它们。

export declare type fEmptyVoid = () => void;
export declare type fEmptyReturn = () => any;
export declare type fArgVoid = (...args: any[]) => void;
export declare type fArgReturn = (...args: any[]) => any;

是这样的:

public isValid: fEmptyReturn = (): boolean => true;
public setStatus: fArgVoid = (status: boolean): void => this.status = status;

为了只使用一种类型作为任何函数类型,我们可以将所有抽象类型组合在一起,如下所示:

export declare type fFunction = fEmptyVoid | fEmptyReturn | fArgVoid | fArgReturn;

然后这样使用它:

public isValid: fFunction = (): boolean => true;
public setStatus: fFunction = (status: boolean): void => this.status = status;

在上面的例子中,一切都是正确的。但是从大多数代码编辑器的角度来看,下面的使用示例是不正确的。

// you can call this function with any type of function as argument
public callArgument(callback: fFunction) {

    // but you will get editor error if call callback argument like this
    callback();
}

正确的编辑召唤是这样的:

public callArgument(callback: fFunction) {

    // pay attention in this part, for fix editor(s) error
    (callback as fFunction)();
}

如果您正在寻找类似于change事件的输入回调函数,则使用以下方法

type Props = {
  callBack:  ChangeEventHandler<HTMLInputElement>;
}

下面是一个接受回调函数的例子

const sqk = (x: number, callback: ((_: number) => number)): number => {
  // callback will receive a number and expected to return a number
  return callback (x * x);
}

// here our callback will receive a number
sqk(5, function(x) {
  console.log(x); // 25
  return x;       // we must return a number here
});

如果你不关心回调函数的返回值(大多数人不知道如何有效地利用它们),你可以使用void

const sqk = (x: number, callback: ((_: number) => void)): void => {
  // callback will receive a number, we don't care what it returns
  callback (x * x);
}

// here our callback will receive a number
sqk(5, function(x) {
  console.log(x); // 25
  // void
});

注意,我用于回调参数的签名…

const sqk = (x: number, callback: ((_: number) => number)): number

我会说这是TypeScript的缺陷,因为我们希望为回调参数提供一个名称。在本例中,我使用_,因为它在sqk函数中不可用。

然而,如果你这样做

// danger!! don't do this
const sqk = (x: number, callback: ((number) => number)): number

它是有效的TypeScript,但是它会被解释为…

// watch out! typescript will think it means ...
const sqk = (x: number, callback: ((number: any) => number)): number

也就是说,TypeScript会认为参数名是number,隐含的类型是any。这显然不是我们想要的,但是,这就是TypeScript的工作方式。

因此,在输入函数参数时,不要忘记提供参数名……尽管这看起来很愚蠢。

全局类型Function用于此目的。

此外,如果你打算用0个参数调用这个回调函数并忽略它的返回值,type () => void匹配所有不带参数的函数。