Koja je sintaksa za TypeScript streličaste funkcije s generičkim tipovima?
Priručnik za TypeScript trenutno nema ništa o streličnim funkcijama. Normalne funkcije mogu se generički tipizirati ovom sintaksom: primjer:
function identity<T>(arg: T): T {
return arg;
}
Koja je sintaksa za funkcije strelice?
Odgovor #1
Uredi
Prema @Thomas komentaru, u novijim TS kompajlerima možemo jednostavno napraviti:
const foo = <T,>(x: T) => x;
Izvorni odgovor
Cjeloviti primjer koji objašnjava sintaksu na koju je Robin referirao... učinio je da mi to postane jasno:
Generičke funkcije
Nešto poput sljedećeg funkcionira dobro:
function foo<T>(x: T): T { return x; }
Međutim, korištenje generičke funkcije sa strelicom neće:
const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag
Zaobilazno rješenje: Koristite extends na generičkom parametru kako biste naznačili kompajleru da je generički, npr.:
const foo = <T extends unknown>(x: T) => x;
Odgovor #2
Ako ste u datoteci .tsx, ne možete samo napisati <T>, ali ovo radi:
const foo = <T, >(x: T) => x;
Za razliku od hakiranja extends {}, ovo hakiranje barem očuva namjeru.
Odgovor #3
Primjer iznad mi je bio zbunjujući. Koristim React i JSX, pa mislim da je to zakompliciralo situaciju.
Dobio sam pojašnjenje iz TypeScript Deep Dive, koji navodi za generičke strelice:
Zaobilazno rješenje: Koristite extends na generičkom parametru kako biste dali do znanja kompajleru da je generički, ovo je proizašlo iz jednostavnijeg primjera koji mi je pomogao.
const identity = < T extends {} >(arg: T): T => { return arg; }
Odgovor #4
Ovo mi odgovara
const Generic = <T> (value: T) => {
return value;
}
Odgovor #5
Specifikacija jezika navodi na str. 64 i sl.
Konstrukcija oblika < T > ( ... ) => { ... } mogla bi se tumačiti kao izraz streličaste funkcije s parametrom tipa ili kao tvrdnja o tipu primijenjena na streličastu funkciju bez parametra tipa. Rješava se kao prvo[..]
primjer :
// 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})
});
};
Odgovor #6
tako kasno, ali s ES6 nema potrebe za extends, i dalje mi radi.... :)
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)
Odgovor #7
Ovo mi odgovara
const logSomething = <T>(something:T): T => {
return something;
}
Odgovor #8
Koristim ovu vrstu deklaracije:
const identity: { <T>(arg: T): T } = (arg) => arg;
Omogućuje definiranje dodatnih svojstava za vašu funkciju ako ikada zatrebate, a u nekim slučajevima pomaže održati tijelo funkcije čišćim od generičke definicije.
Ako vam dodatni atributi (nešto poput prostora imena) nisu potrebni, to se može pojednostaviti na:
const identity: <T>(arg: T) => T = (arg) => arg;
Odgovor #9
iako popularan odgovor s extends {} radi i bolji je od extends any, on prisiljava T da bude objekt
const foo = <T extends {}>(x: T) => x;
da biste to izbjegli i sačuvali sigurnost tipa, možete koristiti extends unknown umjesto toga
const foo = <T extends unknown>(x: T) => x;
Odgovor #10
Način bez korištenja arrow funkcija. Proširujući primjer iz OP-a.
function foo<T>(abc: T): T {
console.log(abc);
return abc;
}
const x = { abc: 123 };
foo(x);
const y = 123;
foo<number>(y);
Osim odgovora koji uključuje umetanje cijele stvari u jednu izjavu:
const yar = <T,>(abc: T) => {
console.log(abc);
return abc;
}
Drugi pristup je imati međutip:
type XX = <T>(abc: T) => T;
const bar: XX = (abc) => {
console.log(abc);
return abc;
}
Igralište
