ジェネリックスのあるTypescript矢印関数の構文は何ですか?


193

typescriptハンドブックは現在、矢印機能について何も持っていません。通常の関数は、一般的に次の構文で型付けできます。例:

function identity<T>(arg: T): T {
    return arg;
}

矢印関数の構文は何ですか?

回答:


237

ロビンによって参照される構文を説明する完全な例...

ジェネリック関数

次のようなものがうまくいきます:

function foo<T>(x: T): T { return x; }

ただし、矢印ジェネリック関数を使用しても、次のことは行われません。

const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag

回避策:ジェネリックパラメーターにextendsを使用して、コンパイラーがジェネリックであることをコンパイラに通知します。例:

const foo = <T extends unknown>(x: T) => x;

1
の事前定義されたジェネリック型を宣言することは可能でしょうconst fooか?つまり、型を指定せずにtype GenericFun<T, A=T> = (payload: A) => T;、const foo: GenericFunまだジェネリックにしTますか?
— ciekawy 2018

@ ciekawy、AFAIK、そうではありません。それは理にかなっていると思います。ジェネリックとは、ある意味でより高次の型を許可することです。他のタイプとGenericFun<T, A=T>を含むセットを定義します。ただし、constなど、ジェネリック型が型注釈を直接構成できるようにすると、静的な安全性が GenericFun<number>GenericFun<string>const foo: GenericFunconst foo: GenericFun<string>const foo: GenericFun<number>
— 損なわ

7
2番目の例は、.tsxファイル(TypeScript + JSX)のエラーのみです。では.ts、あなたが上で見ることができるようにファイルには、罰金の作品活字体の遊び場。
— danvk

48
新しいtypescriptコンパイラconst foo = <T,>(x: T) => x;は、JSXのあいまいさを回避するために末尾のコンマもサポートしています。
— トーマス

1
@danvkこれは、TSファイルでJSXを禁止した人にのみ当てはまることに注意してください。プロジェクトがTSファイルでJSXを許可するように構成されている場合、「拡張」または末尾のコンマが必要です
— Matt

65

上記の例は混乱を招きました。ReactとJSXを使用しているので、シナリオが複雑になっていると思います。

TypeScript Deep Diveから説明を得ました。これには、矢印のジェネリックが記載されています。

回避策:ジェネリックパラメーターでextendsを使用して、ジェネリックであることをコンパイラーに知らせます。これは、私を助けた単純な例からのものです。

    const identity = < T extends {} >(arg: T): T => { return arg; }

9
「T extends any」はvoidをサポートします。
— Mohamed Fakhreddine

48

あなたがいる場合は.tsx、ファイルあなただけ書き込むことはできません<T>が、この作品:

const foo = <T, >(x: T) => x;

extends {}ハックとは対照的に、このハックは少なくとも意図を保持します。


この動作を修正する予定はありますか?
— Alexander Kim

私は...それがこのことについて行うことができるあまりありません... JSXと活字体の一般的な構文はちょうどここに衝突推測
— MB21

1
素晴らしい-これは断然最良の答えです。完璧に動作し、動作をまったく変更しません。
— Geoff Davids

1
デフォルトのタイプパラメータタイプはどうですか?const foo = <T = any,>(x: T) => x動作しません...
— ミハイルヴァシン

34

言語仕様はp.64fで述べています

<T>(...)=> {...}という形式の構造は、型パラメーターを持つ矢印関数式として、または型パラメーターなしの矢印関数に適用される型アサーションとして解析できます。前者として解決される[..]

例:

// helper function needed because Backbone-couchdb's sync does not return a jqxhr
let fetched = <
           R extends Backbone.Collection<any> >(c:R) => {
               return new Promise(function (fulfill, reject) {
                   c.fetch({reset: true, success: fulfill, error: reject})
               });
           };

14

これは私のために働く

const Generic = <T> (value: T) => {
    return value;
} 

4
.tsファイルにある場合、これは機能します。それ以外の場合は、延長する必要があります。
— kushalvm

1
完全に正常に動作します。typescript
— play.js.org

これは、vscodeの.tsファイルと.tsxファイルでうまく機能しています
— Shubhan

3

extends {}作品で人気のある答えはと比べて優れていますがextends any、は強制的にTオブジェクトになります

const foo = <T extends {}>(x: T) => x;

これを回避し、タイプセーフを保持するには、extends unknown代わりに使用できます

const foo = <T extends unknown>(x: T) => x;

1

このタイプの宣言を使用します。

const identity: { <T>(arg: T): T } = (arg) => arg;

必要に応じて関数に追加の小道具を定義することができ、場合によっては、関数の本体を一般的な定義からよりクリーンに保つのに役立ちます。

追加の小道具(名前空間のようなもの)が必要ない場合は、次のように簡略化できます。

const identity: <T>(arg: T) => T = (arg) => arg;

1

とても遅いですが、ES6では拡張する必要はありません。

let getArray = <T>(items: T[]): T[] => {
    return new Array<T>().concat(items)
}

let myNumArr = getArray<number>([100, 200, 300]);
let myStrArr = getArray<string>(["Hello", "World"]);
myNumArr.push(1)
console.log(myNumArr)

これは私にとっては機能しません<T, >。次のようにカンマを追加する必要があります。@jbmilgromの回答の下の@Thomasコメントで説明されているように
— アポロ

投稿する前に、他のソリューションを読んでください。あなたの解決策はすでに説明付きで投稿されています。.tsxファイルではなく、.tsファイル内でのみ機能します。
— Isaac Pak
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.