Care este sintaxa pentru funcțiile săgeată Typescript cu generice?


Manualul TypeScript nu are în prezent nimic despre funcțiile săgeată. Funcțiile normale pot fi tipizate generic cu această sintaxă: exemplu:

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

Care este sintaxa pentru funcțiile săgeată?

Răspuns #1

Editează

Conform comentariului lui @Thomas, în compilatoarele TS mai noi, putem pur și simplu să facem:

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

Răspuns original

Exemplul complet care explică sintaxa menționată de Robin... mi-a făcut-o clar:

Funcții generice

Ceva de genul următor funcționează bine:

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

Totuși, utilizarea unei funcții generice săgeată nu va:

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

Soluție alternativă: Folosiți extends pe parametrul generic pentru a sugera compilatorului că este un generic, de exemplu:

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

Răspunsul #2

Dacă te afli într-un fișier .tsx, nu poți pur și simplu să scrii <T>, dar asta funcționează:

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

Spre deosebire de trucul extends {}, acest truc păstrează cel puțin intenția.

Răspunsul #3

Am găsit exemplul de mai sus confuz. Folosesc React și JSX, așa că cred că a complicat scenariul.

Am obținut clarificări din TypeScript Deep Dive, care afirmă despre genericele săgeată:

Soluție alternativă: Folosește extends pe parametru generic pentru a sugera compilatorului că este generic, aceasta provine dintr-un exemplu mai simplu care m-a ajutat.

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

Răspunsul #4

Aceasta funcționează pentru mine

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

Răspunsul #5

Specificația limbajului spune la p.64 și următoarele

O construcție de forma < T > ( ... ) => { ... } ar putea fi interpretată ca o expresie de funcție săgeată cu un parametru de tip sau ca o aserțiune de tip aplicată unei funcții săgeată fără parametru de tip. Este rezolvată ca prima[..]

exemplu :

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

Răspuns #6

atât de târziu, dar cu ES6 nu e nevoie să o extind, tot funcționează pentru mine.... :)

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)

Răspunsul #7

Aceasta funcționează pentru mine

const logSomething = <T>(something:T): T => {
    return something;
}

Răspuns #8

Folosesc acest tip de declarație:

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

Permite definirea de proprietăți suplimentare pentru funcția ta dacă vreodată ai nevoie, și în unele cazuri, ajută la menținerea corpului funcției mai curat de definiția generică.

Dacă nu ai nevoie de proprietățile suplimentare (un fel de spațiu de nume), poate fi simplificat astfel:

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

Răspunsul #9

în timp ce răspunsul popular cu extends {} funcționează și este mai bun decât extends any, acesta obligă T să fie un obiect

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

pentru a evita acest lucru și a păstra siguranța tipului, poți folosi extends unknown în schimb

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

Răspuns #10

Modul fără funcție săgeată. Extinderea exemplului din OP.

function foo<T>(abc: T): T {
    console.log(abc);
    return abc;
}

const x = { abc: 123 };
foo(x);

const y = 123;
foo<number>(y);

În afară de răspunsul de a încorpora totul într-o singură declarație:

const yar = <T,>(abc: T) => {
    console.log(abc);
    return abc;
}

O altă abordare este să existe un tip intermediar:

type XX = <T>(abc: T) => T;

const bar: XX = (abc) => {
    console.log(abc);
    return abc;
}

Teren de joacă