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


313

現在、私は型定義を持っています:

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

私は次のようなものが必要です:

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

ただし、2つ目は受け入れられません。

回答:


285

グローバルタイプFunctionはこの目的に役立ちます。

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



13
引数と戻り値を定義する必要があるため、これは基本的なタイプではありません。コールバックのようなもの:(number:number)=> void; 型チェックには、callback:functionよりもはるかに便利です。だろう。
kpup

@kpup明確に言うと、この回答の最初の行に示されているように大文字のFを使用せずFunction、2番目のパラグラフ(タ​​イプ() => voidまたはユースケースに一致するものを使用)が好ましいと言っていますか?
ルフィン、

2
FWIW、関数型のドキュメントはこちらから
18

191

v1.4のTypescriptには、type型のエイリアスを宣言するキーワードがあります(typedefC / C ++のに類似)。このようにして、コールバックタイプを宣言できます。

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ハンドラーなどに役立ちます。

関数は、このように好きなだけ強く型付けできますが、型エイリアスですべてを特定しようとすると、夢中になって組み合わせの問題に遭遇する可能性があります。


1
の間Function(...args: any[]) => any何が好ましいですか?
ahong

@ahong:個人的には署名を提供するので後者を好みます...通常。...args: any[]あまり役に立ちません。
Ed S.

type CallbackFunctionSomeVariadic = (arg1: string, arg2: number, ...args: any[]) => void;私が探していたもの、ty。
aqteifan

61

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

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

34

コールバックを受け入れる関数の例を次に示します

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の欠陥だと思います。この場合_sqk関数内では使用できないため使用しました。

ただし、これを行うと

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

それはだ有効な活字体が、それは次のように解釈されます...

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

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

そのため、関数のパラメーターを入力するときにパラメーター名を指定することを忘れないでください。


32

さまざまな方法でインターフェイスで関数タイプを定義できます。

  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;

}

10

4つの抽象関数タイプがあります。関数が引数を取るかどうか、データを返すかどうかがわかっている場合は、それらを個別に使用できます。

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;

関数型として1つの型のみを使用するには、次のようにすべての抽象型を組み合わせることができます。

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

2

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です。メソッドは、のように組み込み型と組み合わせて少し実用的であるように(サウンドでなくても)より寛容にチェックされますArray

概要

  • 関数のプロパティとメソッドの宣言には型の違いがあります
  • 可能であれば、より強い型の関数プロパティを選択します

Playgroundサンプルコード

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.