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.