ChatGPT解决这个技术问题 Extra ChatGPT

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

目前我的类型定义为:

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

我需要类似的东西:

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

但第二个不被接受。

它是大写 callback:Function 而不是 lower case callback:function
我发现 Function 不兼容是一种情况,所以我创建了一个“AnyFunction”类型:export type AnyFunction = (...args: any[]) => any;

R
Ryan Cavanaugh

全局类型 Function 用于此目的。

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


basic types 中缺少这个东西
它不是基本类型,因为您应该定义参数和返回值。类似于回调:(数字:数字)=> void;类型检查比回调更有用:函数;将会。
FWIW,提供有关函数类型的文档 here
@SgtPooki 鉴于 Ryan is the lead of the Typescript team 和您的编辑非常重要,您确定它们更多地属于编辑而不是您自己的答案吗?我认为您的补充是有效的建议,但鉴于 Ryan 的权威,我很惊讶在这里发现您的编辑,尤其是在 contradict or change the meaning of the original post 的地方。
注意 ESLint gives some advice against using Function 直接作为类型 -- 引用“不要使用 Function 作为类型。Function 类型接受任何类似函数的值。它在调用函数时不提供类型安全,它可以是常见的错误来源。它还接受诸如类声明之类的东西,它们将在运行时抛出,因为它们不会被 new 调用。”
D
David G

来自 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 处理程序之类的东西很有用。

可以用这种方式对函数进行任意强度的类型化,但如果您尝试使用类型别名来确定所有内容,您可能会被带走并遇到组合问题。


Function(...args: any[]) => any 之间首选什么?
@ahong:我个人更喜欢后者,因为它通常提供签名。 ...args: any[] 不是很有用。
type CallbackFunctionSomeVariadic = (arg1: string, arg2: number, ...args: any[]) => void; 我在寻找什么,ty。
似乎我能够在其他组件中导出和重用定义,例如 export type CallbackFunctionSomething = (page: number, sort: blablabla) => void
我发现了一件有趣的事情:Function(...args: any[]) => any 不一样
b
blorkfish

根据 Ryan 的回答,我认为您正在寻找的界面定义如下:

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

H
Humayoun_Kabir

您可以通过各种方式在接口中定义函数类型,

一般方式:

export interface IParam {
  title: string;
  callback(arg1: number, arg2: number): number;
}

如果您想使用属性语法,

export interface IParam {
  title: string;
  callback: (arg1: number, arg2: number) => number;
}

如果你先声明函数类型,

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

你也可以声明一个函数类型文字,这意味着一个函数可以接受另一个函数作为它的参数。参数化函数也可以作为回调调用。

export interface IParam{
  title: string;
  callback(lateCallFn?:
             (arg1:number,arg2:number)=>number):number;

}

这就是我想要的。
M
Mulan

这是一个接受回调的函数示例

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

我会说这是 TypeScript 的缺陷,因为我们需要为回调参数提供一个 name。在这种情况下,我使用了 _,因为它在 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 会认为参数 namenumber,隐含类型是 any。这显然不是我们想要的,但可惜的是,TypeScript 就是这样工作的。

因此,在键入函数参数时不要忘记提供参数名称......看起来很愚蠢。


A
Artur T

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

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

D
Ders

请注意,TypeScript ESLint plugin 具有推荐的规则 ban-types(错误)和 no-explicit-any(警告)。

避免使用 Function 类型,因为它提供的安全性很小

遵守这些规则,也许最好的解决方案是,

callback: (...args: unknown[]) => unknown

C
Community

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

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

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

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

TS 2.6 以来有一个重要的打字区别:

当声明 函数属性 时,您会在 --strict--strictFunctionTypes 模式下获得更强的(“声音”)类型。举个例子:

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 下的参数中是双变量和函数属性 contravariant。方法仍然是 checked more permissively(即使不健全)与 Array 等内置类型结合使用更实用。

概括

函数属性和方法声明之间存在类型差异

如果可能,为更强的类型选择函数属性

Playground sample code


r
rksh1997

希望这会有所帮助...

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;

}


E
Edwin Pratt

我刚刚开始使用 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);