如何定义类型的函数回调(作为任何函数类型,不是通用的任何)在一个方法参数中使用

目前我有类型定义为:

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

我需要这样的东西:

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

但是第二项不被接受。

554725 次浏览

全局类型Function用于此目的。

此外,如果您打算调用带有0个参数的回调并忽略其返回值,则() => void类型匹配所有不带参数的函数。

根据Ryan的回答,我认为你所寻找的接口定义如下:

interface Param {
title: string;
callback: () => void;
}

从v1.4开始的Typescript有type关键字,它声明了一个类型别名(类似于C/ c++中的typedef)。你可以这样声明你的回调类型:

type CallbackFunction = () => void;

它声明了一个不接受参数且不返回任何值的函数。接受零个或多个任意类型参数且不返回任何值的函数是:

type CallbackFunctionVariadic = (...args: any[]) => void;

然后你可以说,例如,

let callback: CallbackFunctionVariadic = function(...args: any[]) {
// do some stuff
};

如果你想要一个函数接受任意数量的参数并返回任何值(包括void):

type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any;

你可以指定一些强制性参数,然后是一组额外的参数(比如一个字符串,一个数字,然后是一组额外的参数),这样:

type CallbackFunctionSomeVariadic =
(arg1: string, arg2: number, ...args: any[]) => void;

这对于EventEmitter处理器之类的东西很有用。

在这种方式下,函数的类型可以随心所欲,尽管如果您试图用类型别名确定所有内容,可能会失去控制并遇到组合问题。

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

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
});

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

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

I would say this is a TypeScript deficiency because we are expected to provide a name for the callback parameters. In this case I used _ because it's not usable inside the sqk function.

However, if you do this

// 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的工作方式。

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

你可以用多种方式在接口中定义函数类型,

  1. 一般方法:
export interface IParam {
title: string;
callback(arg1: number, arg2: number): number;
}
  1. 如果你想使用属性语法,
export interface IParam {
title: string;
callback: (arg1: number, arg2: number) => number;
}
  1. 如果先声明函数类型,
type MyFnType = (arg1: number, arg2: number) => number;


export interface IParam {
title: string;
callback: MyFnType;
}

使用非常直接,

function callingFn(paramInfo: IParam):number {
let needToCall = true;
let result = 0;
if(needToCall){
result = paramInfo.callback(1,2);
}


return result;
}
  1. 你也可以声明一个函数类型文字,这意味着一个函数可以接受另一个函数作为它的形参。参数化函数也可以作为回调函数调用。
export interface IParam{
title: string;
callback(lateCallFn?:
(arg1:number,arg2:number)=>number):number;


}

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

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)();
}

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 ...

从技术上讲,方法是bivariant,函数属性是< em >逆变< / em >。方法仍然是检查更允许(即使不是健全的),以便与Array这样的内置类型结合起来更实用。

总结

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

<一个href = " https://www.typescriptlang.org/play/?ts=3.8.3& ssl = 30, ssc = 80, pln = 25, pc = 1 #代码/ JYOwLgpgTgZghgYwgAgIImAWzgG2QbwFgAoZM5EOTCALmQGcwpQBzEgXxJNElkRQAiAexbIIAD0ggAJvTQZseIqXIIAFnHoR6dAEZChOCHBAcuxHtHhJkAYThgxkiDLnosuAiXLIEUCBAADjrI + obGpsScxNzgVvzIAApwUFQAYiCJUEKBXipkCLg4uogA1nQAFHB07ooAlMgAvAB8yABuQsDSANzIAPR9yDAAriAIYMBCIMiB2YHQYACeZjEWcXw2yamYALIQYGpC0nk + hTjFZVU1Crh1dB1dvQPI1AdHKyQIU4zI0iL25xKCFKTWQFWkdGELDu7U6xxaBGQ0S + IB + hTAAIuwNBFQQdHsYBhD3hrXwSM + 30 cjg8oexqjbjtb1xknkjckappjq2eizGEymMzmC0W7RSwBMYApqMcgRSVAAjPK6Ft0pk5qCyWcseVfv8ivSkf1BtBslA6CAhFT6PRgCxKLojFKfrLtvKAEzKuWYDJZHIa3z6sp0amKOllQ3PADuQigpXo5mer0OxzaYolTplXo9SS9eze8MRWvpdD+LDD2PYRooQkjyGAjmjsbkcBYcFAyAAdF3zD3ViQgA" rel="nofollow noreferrer">操场样例代码

希望这对你有所帮助……

interface Param {
title: string;
callback: (error: Error, data: string) => void;
}


或在函数中


let myfunction = (title: string, callback: (error: Error, data: string) => void): string => {


callback(new Error(`Error Message Here.`), "This is callback data.");
return title;


}


我刚开始使用Typescript,我一直试图解决类似的问题,就像这样;如何告诉Typescript,我传递一个回调没有interface

在浏览了Stack Overflow和GitHub问题的一些答案后,我终于找到了一个解决方案,可以帮助任何有同样问题的人。

函数的类型可以用(arg0: type0) => returnType定义,我们可以在另一个函数的形参列表中使用这个类型定义。

function runCallback(callback: (sum: number) => void, a: number, b: number): void {
callback(a + b);
}


// Another way of writing the function would be:
// let logSum: (sum: number) => void = function(sum: number): void {
//     console.log(sum);
// };
function logSum(sum: number): void {
console.log(`The sum is ${sum}.`);
}


runCallback(logSum, 2, 2);

定义函数类型有多种方法;然而,有些比其他的好。

虽然可以使用<强> # EYZ0 < / >强,但JavaScript函数对象不要这样做
来源:TypeScript ESLint插件推荐规则ban-types

  • 避免使用Function类型,因为它提供的安全性很少,原因如下:
    • 它在调用值时不提供类型安全,这意味着很容易提供错误的参数。
    • 它接受类声明,类声明在调用时会失败,因为调用时没有new关键字。

TypeScript支持多种其他方式。最常见的是使用函数类型表达式。这个方法非常类似于箭头功能

如果已知参数和返回值是某种形式,则应该键入它们。
例如,< / p >

interface Param {
callback: (foo: string, bar: number) => void
}

注意,这些类型可以根据需要非常复杂,例如使用对象类型从其他类型创建的类型

如果类型确实未知然后更喜欢unknown而不是any
来源:TypeScript ESLint插件推荐规则no-explicit-any

当使用any时,所有围绕该值的编译器类型检查都将被忽略。

从TS文档中,

unknownany的类型安全对应。

因此,使用传播的语法

interface Params {
callback: (...args: unknown[]) => unknown
}

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

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