TypeScript - Derste, arayüzdeki isteğe bağlı özelliklerin derleme zamanında null olmadığını doğrulama


Javascript'te, bir constructor'a bir options object geçmeyi ve beklediğim eksik özellikleri varsayılan değerlerle doldurmayı seviyorum:

function foo(options) {
   if(options.a == undefined) {
      options.a = 1;
   }
   if(options.b == undefined) {
      options.b = 'hello';
   }
   this.options = options;
}

new foo({a: 10});

Bu deseni Typescript'te uygulamaya çalışırken, şunlara sahibim:

interface Options {
    a?: number;
    b?: string;
}

class Foo {
   options: Options;
   constructor(options: Options) {
      if(options.a == undefined) {
         options.a = 1;
      }
      if(options.b == undefined) {
         options.b = 'hello';
      }
      this.options = options;
   }
}

Daha sonra class içinde options kullandığımda tüm özelliklerin tanımlı olduğunu biliyorum. Ancak, Typescript bundan habersizdir, bu yüzden bu ifade bir hata üretir:

let a:Number = this.options.a; // Argument of type 'number | undefined' is not assignable to parameter of type number.

Ayrıca, class içindeki kodun daha sonra özelliğe null veya undefined değeri atamasına izin vermek istemiyorum:

this.options.a = undefined; // should produce compiler error

Tiplerimi tanımlamanın bir yolu var mı, böylece class içinde kullanıldığında Options özellikleri null olmasın iki ayrı Options arayüzü tanımlamadan?

Örneğin, dahili kullanım için başka bir interface oluşturabileceğimi biliyorum:

interface OptionsSafe {
    a: number;
    b: string;
}

// in Foo constructor
this.options = {
    a: a != undefined ? options.a! : 1,
    b: b != undefined ? options.b! : 'hello'
};

Ama sonra seçeneklerin özelliklerini iki ayrı arayüzde tanımlamam ve onların her zaman senkronize olmasını sağlamam gerekiyor (bu çözüm, eğer Typescript her iki arayüzü tek bir tanımdan oluşturabiliyorsa harika olur).

Ayrıca tüm özellikleri ayrı, isteğe bağlı argümanlar olarak geçirmek de istemiyorum, çünkü

  1. onlarca veya daha fazla seçenek olabilir ve
  2. fonksiyon argümanları Options arayüzünden sapabilir, bu yüzden yine de iki "arayüzü" senkronize tutmam gerekiyor.

Cevap #1

Bir seçenek, TypeScript'in sağladığı yerleşik Partial türünü kullanmaktır. Bu, sizin için "iki Options arayüzü tanımlamak" ile çok yakın olabilir, ama ne demek istediğimi yine de göstereceğim.

Typescript, type Partial<T>={[P in keyof T]?: T[P]} olarak tanımlanan yerleşik bir Partial türü sağlar.

Bunun anlamı, sadece tüm üyeleriyle Options arayüzünü tanımlayabilir, ancak yapıcı fonksiyonunuz için bunun kısmi (partial) versiyonunu kullanabilirsiniz. Şöyle:

interface Options {
    a: number;
    b: string;
}

class Foo {
   options: Options;
   constructor(options: Partial<Options>) {
      const defaultOptions = {
          a: 1,
          b: 'hello'
      };

      this.options = Object.assign(defaultOptions, options);
   }
}

Typescript'in nesnede tüm gerekli özelliklere sahip olduğunuzu doğru bir şekilde çıkarabilmesi için, kullandığınız if deyimi mantığından yukarıdakine daha benzer bir şeye geçmeniz gerekecek.

İlgili makaleler