Generic ile daktilo okları işlevlerinin sözdizimi nedir?


195

Daktilo el kitabının şu anda ok işlevleri hakkında hiçbir şey yok. Normal işlevler genel olarak bu sözdizimi ile yazılabilir: örnek:

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

Ok işlevleri için sözdizimi nedir?

Yanıtlar:


240

Robin'in referans aldığı sözdizimini açıklayan tam örnek ... benim için eve getirdi:

Genel fonksiyonlar

Aşağıdaki gibi bir şey iyi çalışıyor:

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

Ancak bir ok genel işlevi kullanıldığında:

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

Geçici çözüm: Derleyiciye genel olduğunu göstermek için generic parametresindeki uzantıları kullanın, örneğin:

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

1
için önceden tanımlanmış bir jenerik tip beyan etmek mümkün müdür const foo? yani type GenericFun<T, A=T> = (payload: A) => T;o zaman const foo: GenericFunbir Ttür sağlamadan hala genel yapmak ?
ciekawy

@ciekawy, AFAIK, değil ve bence bu mantıklı. Jenerikler bir anlamda daha üst düzey tiplere izin vermekle ilgilidir. diğer türleri ve diğerlerini GenericFun<T, A=T>içeren bir kümeyi tanımlar . Bununla birlikte, genel türlerin doğrudan bir tür ek açıklama oluşturmasına izin vermek - örn. Const - ancak, örneğin veya GenericFun<number>GenericFun<string>const foo: GenericFunconst foo: GenericFun<string>const foo: GenericFun<number>
jbmilgrom

7
İkinci örneğiniz yalnızca bir .tsxdosyadaki bir hatadır (TypeScript + JSX). Bir .tsdosyada, TypeScript oyun alanında gördüğünüz gibi iyi çalışıyor .
danvk

49
Daha yeni const foo = <T,>(x: T) => x;dizgi derleyicileri de JSX belirsizliğini azaltmak için sondaki virgülleri destekler .
Thomas

1
@danvk Bu sadece TS dosyalarında JSX yasaklayanlar için geçerlidir - bir proje TS dosyalarında JSX'e izin verecek şekilde yapılandırılmışsa, hala "genişletir" veya sondaki virgül gerekir
Matt

65

Yukarıdaki örneği kafa karıştırıcı buldum. React ve JSX kullanıyorum, bu yüzden senaryoyu karmaşık hale getiriyor.

Ok jeneriklerini belirten TypeScript Deep Dive'dan açıklama aldım :

Geçici çözüm: Derleyiciye genel olduğunu göstermek için generic parametresinde uzantıları kullanın, bu bana yardımcı olan daha basit bir örnekten geldi.

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

9
"T herhangi birini uzatır" geçersizliği destekleyecektir.
Mohamed Fakhreddine

48

Bir .tsxdosyadaysanız yazamazsınız <T>, ancak bu işe yarar:

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

Saldırının aksine extends {}, bu saldırı en azından niyetini korur.


Bu davranışı düzeltmeyi planlıyorlar mı?
Alexander Kim

Sanırım bu konuda yapılabilecek çok şey yok ... JSX ve Typescript genel sözdizimleri sadece burada çatışma ..
mb21

1
Fantastik - bu en iyi cevap: mükemmel çalışıyor ve davranışları hiç değiştirmiyor!
Geoff Davids

1
Varsayılan tip parametre tipi ne olacak? const foo = <T = any,>(x: T) => xçalışmıyor ...
Mikhail Vasin

34

Dil belirtimi p.64f'de yazıyor

<T> (...) => {...} formunun bir yapısı, bir tür parametresiyle bir ok işlevi ifadesi veya tür parametresiz bir ok işlevine uygulanan bir tür iddiası olarak ayrıştırılabilir. Eski gibi çözülür [..]

misal:

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


3

popüler cevap extends {}işe yarıyor ve daha iyi extends anyolsa Tda, nesneyi

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

Bundan kaçınmak ve tip güvenliğini korumak için extends unknownbunun yerine

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

2

çok geç, ama ES6 ile gerek yok benim için hala çalışır .... :)

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)

Bu benim için çalışmıyor, ben şöyle bir virgül eklemek zorunda: <T, >. @jbmilgrom 'cevabı altında @Thomas yorumunda açıklandığı gibi
apollo

Biri göndermeden önce diğer çözümleri okumalısınız. Çözümünüz zaten bir açıklama ile gönderildi. Yalnızca .ts dosyasının içinde çalışır, bir .tsx dosyası içinde çalışmaz.
Isaac Pak

1

Bu tür bir beyanı kullanmak için:

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

İhtiyacınız olursa, işlevinize ek desteklerin tanımlanmasına izin verir ve bazı durumlarda işlev gövdesini genel tanımdan daha temiz tutmaya yardımcı olur.

Ek desteklere (ad alanı bir şey) ihtiyacınız yoksa, basitleştirilebilir:

const identity: <T>(arg: T) => T = (arg) => arg;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.