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

May 01 2023
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 Casting'den Kaçının FruitType<T> döndüren işlev tanımını uyguladığımızda, bunun dahili bir type cast (ugh) gerektirdiğini görüyoruz.
Portakal mı Elma mı?

// 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.