Vad är syntaxen för Typescript-pilfunktioner med generiska typer?
Typescript-handboken har för närvarande inget om arrow-funktioner. Vanliga funktioner kan generiskt typas med denna syntax: exempel:
function identity<T>(arg: T): T {
return arg;
}
Vad är syntaxen för pilfunktioner?
Svar #1
Redigera
Enligt @Thomas kommentar, i nyare TS-kompilatorer kan vi helt enkelt göra:
const foo = <T,>(x: T) => x;
Originalt svar
Det fullständiga exemplet som förklarar syntaxen som Robin refererade till... fick det att gå hem för mig:
Generiska funktioner
Något som följande fungerar bra:
function foo<T>(x: T): T { return x; }
Men att använda en generisk pilfunktion kommer inte att:
const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag
Lösning: Använd extends på den generiska parametern för att ge kompilatorn en antydan att det är generiskt, t.ex.:
const foo = <T extends unknown>(x: T) => x;
Svar #2
Om du är i en .tsx-fil kan du inte bara skriva <T>, men detta fungerar:
const foo = <T, >(x: T) => x;
Till skillnad från extends {}-knepet bevarar detta knep åtminstone avsikten.
Svar #3
Jag tyckte att exemplet ovan var förvirrande. Jag använder React och JSX, så jag tror att det gjorde scenariot mer komplicerat.
Jag fick förtydligande från TypeScript Deep Dive, som säger om pilar med generiska typer:
Tillfällig lösning: Använd extends på den generiska parametern för att ge kompileraren en antydan om att det är en generisk typ, detta kommer från ett enklare exempel som hjälpte mig.
const identity = < T extends {} >(arg: T): T => { return arg; }
Svar #4
Det här fungerar för mig
const Generic = <T> (value: T) => {
return value;
}
Svar #5
Språkspecifikationen säger på s.64f
En konstruktion av formen < T > ( ... ) => { ... } kan tolkas som ett pilfunktionuttryck med en typparameter eller en typförsäkran som tillämpas på en pilfunktion utan typparameter. Den löses som det förstnämnda[..]
exempel :
// 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})
});
};
Svar #6
så sent, men med ES6 behövs det inte att ärva, det fungerar fortfarande för mig.... :)
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)
Svar #7
Det här fungerar för mig
const logSomething = <T>(something:T): T => {
return something;
}
Svar #8
Jag använder den här typen av deklaration:
const identity: { <T>(arg: T): T } = (arg) => arg;
Det tillåter att definiera ytterligare egenskaper för din funktion om du någonsin behöver det, och i vissa fall hjälper det att hålla funktionskroppen renare från den generiska definitionen.
Om du inte behöver de ytterligare egenskaperna (något i stil med ett namnrymd), kan det förenklas till:
const identity: <T>(arg: T) => T = (arg) => arg;
Svar #9
medan det populära svaret med extends {} fungerar och är bättre än extends any, tvingar det T att vara ett objekt
const foo = <T extends {}>(x: T) => x;
för att undvika detta och bevara typsäkerheten kan du istället använda extends unknown
const foo = <T extends unknown>(x: T) => x;
Svar #10
Sättet utan pilfunktion. Utvecklar exemplet från OP.
function foo<T>(abc: T): T {
console.log(abc);
return abc;
}
const x = { abc: 123 };
foo(x);
const y = 123;
foo<number>(y);
Bortsett från svaret att bädda in hela saken i ett uttalande:
const yar = <T,>(abc: T) => {
console.log(abc);
return abc;
}
Ett annat tillvägagångssätt är att ha en mellanliggande typ:
type XX = <T>(abc: T) => T;
const bar: XX = (abc) => {
console.log(abc);
return abc;
}
Lekplats
