TypeScript'te Birden Çok Dönüş Türünü Daraltmak

// multiple return types
function getFruit({withCitrus: boolean}): Apples | Oranges;
// Why can't we write this?! We know Oranges are returned
var fruit: Oranges = getFruit({ withCitrus: true }); // error
// type guard distinguishes between Apples and Oranges
function isOranges(fruit: Apples | Oranges): fruit is Oranges {
return "VitaminC" in (fruit as Oranges);
}
var fruits: Apples | Oranges = getFruit({withCitrus: true);
if (isOranges(fruits)) {
// type guard narrowed the type to Oranges
var oranges: Oranges = fruits; // ok, no compilation error
}
Bu makalede Maurer Krisztián, bir işlevin bağımsız değişkenlerini dönüş türüne bağlamak için Genel'in nasıl kullanılacağını gösterir.
type FruitType<T> =
T extends { withCitrus: false } ? Apples :
T extends { withCitrus: true | undefined } ? Oranges :
Oranges;
function getFruit<T extends { withCitrus: boolean }>(opt?: T): FruitType<T>;
var apples: Apples = getFruit({withCitrus: false}); // ok
var oranges1: Oranges = getFruit({withCitrus: true}); // ok
var oranges2: Oranges = getFruit(); // ok
Tip Dökümden Kaçının
Geri dönen işlev tanımını uyguladığımızda, FruitType<T>
bunun dahili bir tür atama (ugh) gerektirdiğini görüyoruz. Bir aşırı yük fonksiyonu eklersek, dönüş tipini uygulamadan ayırarak daraltmaya devam edebiliriz.
interface IOptions { withCitrus?: boolean };
const DEFAULT_FRUIT_OPTS = { withCitrus: true } as const;
function getFruit<T>(opt?: T extends IOptions ? T : never): FruitType<T>;
function getFruit(opts?: IOptions)
{
const _opts = { ...DEFAULT_FRUIT_OPTS, ...opts };
return _opts.withCitrus ? bagOfOranges : bagOfApples;
}
Diğer Seçeneklere İzin Ver
Başka bir seçenek eklemek, dönüş tipi daraltmayı engellemez.
interface IOptions {
withCitrus?: boolean,
hasColor?: Apples['color'] | Oranges['color'],
};
var apples: Apples = getFruit({withCitrus: false, hasColor: "red"}); // ok
var oranges1: Oranges = getFruit({withCitrus: true, hasColor: "orange"}); // ok
var oranges2: Oranges = getFruit({hasColor: "red"}); // ok
TypeScript'i ne kadar iyi geliştirirsek geliştirelim, yine de dönüş türünün daraltılamadığı bazı durumlar vardır.
var opts5 = { withCitrus: false }; // boolean
var apple5: Apples = getFruit(opts); // error
var opts6: IOptions = { withCitrus: true }; // boolean
var orange6: Oranges = getFruit(opts); // error
var opts7 = { withCitrus: false } as const; // false
var apple7: Apples = getFruit(opts); // ok
Uç Kasa Yazma
Bazı hatalara neden olabilecek tür tanımına sahip birkaç potansiyel son durumumuz var FruitType<T>
: (1) varsayılan seçenek değeri için tek doğruluk kaynağı ve (2) bir Dağıtıcı Koşullu Türü tetikleme .
Daha derin bir açıklama için bu TS Playground'a bakın.
Son şekil
Hepsini birbirine bağlamak.
type FruitType<T> =
T extends { withCitrus?: infer B } ?
[boolean] extends [B] ? Oranges | Apples :
B extends undefined | typeof DEFAULT_FRUIT_OPTS.withCitrus ?
Oranges : Apples :
Oranges;
function getFruit<T>(opt?: T extends IOptions ? T : never): FruitType<T>;
function getFruit(opts?: IOptions)
{
const _opts = { ...DEFAULT_FRUIT_OPTS, ...opts };
return _opts.withCitrus ? bagOfOranges : bagOfApples;
}
Bu makalede, bağımsız değişken listesini kullanarak bir işlevin çoklu dönüş türlerinin nasıl daraltılacağını açıklıyoruz; çağıranın beklediği dönüş tipini derleyiciye nasıl bildireceğimizi gösteriyoruz. Bunu tip güvenli bir şekilde yapıyoruz ve gereksiz tip dökümünden kaçınıyoruz. Türleri ve varsayılanları değiştirirken hataları önlemek için ek adımları teşvik ediyoruz. Son olarak, dönüş tipi daraltmanın, tip değişmezleri veya tip korumaları kullanarak ekstra odaklanma gerektirdiği çeşitli uç durumları keşfediyoruz.
Lütfen yorum yapın ve ne düşündüğünüzü bana bildirin.