web-dev-qa-db-ja.com

Typescript:メソッドパラメータで使用される関数コールバックの型を定義する方法(汎用型ではなく、任意の関数型として)

現在私は型の定義があります:

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

私は何かが必要です:

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

しかし、2番目のものは受け入れられていません。

200

グローバルタイプFunctionはこの目的にかないます。

さらに、このコールバックを0個の引数で呼び出して戻り値を無視する場合は、() => void型が引数を取らないすべての関数に一致します。

192
Ryan Cavanaugh

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ハンドラのようなものに役立ちます。

関数をこのように強く型付けすることもできますが、型の別名を使ってすべてを釘付けしようとすると、動かなくなって組み合わせの問題に遭遇する可能性があります。

134
David G

Ryanの答えに続いて、あなたが探しているインターフェースは次のように定義されていると思います。

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

これは、コールバックを受け付ける関数の例です。

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

コールバックパラメータに name を指定することが期待されているので、これはTypeScriptの欠点です。この場合、sqk関数内では使用できないので、_を使用しました。

ただし、これを行うと

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

これは valid TypeScriptですが、...と解釈されます。

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

つまり、TypeScriptはパラメータ name numberであり、暗黙の型がanyであると見なします。これは明らかに私たちが意図したものではありませんが、残念なことにTypeScriptのしくみです。

関数パラメータを入力するときは、パラメータ名を忘れずに入力してください。

26
user633183

あなたは様々な方法でインターフェースで関数型を定義することができます、

  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. 関数型リテラルも宣言できます。これは、関数が別の関数をパラメータとして受け入れることができることを意味します。 parameterize関数はコールバックとしても呼び出せます。
export interface IParam{
  title: string;
  callback(lateCallFn?:
             (arg1:number,arg2:number)=>number):number;

}
11
Humayoun_Kabir