Typescript, bir fonksiyon tipi ile bir nesne tipinin birleşimindeki özellikleri kontrol etmeyi başaramıyor


Typescript, bir fonksiyon türü ile bir nesne türünün birleşimindeki özellikleri, başka bir nesne ve fonksiyon birleşimi ile kesiştirirken kontrol etmeyi başaramıyor.

Bu, sorunu yeniden üretmek için minimal bir depo. Bunu arşivlemenin doğru yolu nedir?

type Component = () => {};
type OneType =
  | Component
  | { component: Component }
  | { getComponent: () => Component }

type AnotherType =
  | Component
  | ({ // static properties of Component
    option?: string;
    anotherOption?: string;
  } & OneType);

type AnyObject = {
  [name: string]: AnotherType
}

function aFunction(comps: AnyObject, name: string) {
  const comp = comps[name];

  // [ts] fail here: Property 'component' does not exist on type 'AnotherType'
  if (comp.component) {
    return comp.component;
  }

  // [ts] fail here: Property 'getComponent' does not exist on type 'AnotherType'
  if (typeof comp.getComponent === 'function') {
    return comp.getComponent();
  }

  return comp;
}

Burası Playgroud: Playgroud deposu

Cevap #1

Typescript, bir birlikteki ortak özelliklere erişmenize izin verir. Bir çözüm, birliği hangi üyenin konuştuğunu derleyiciye inandırmak için bir in tür-koruma kullanmaktır.

type Component = () => {};
type OneType =
  | Component
  | { component: Component }
  | { getComponent: () => Component }

type AnotherType =
  | Component
  | ({ // static properties of Component
    option?: string;
    anotherOption?: string;
  } & OneType);

type AnyObject = {
  [name: string]: AnotherType
}

function aFunction(comps: AnyObject, name: string) {
  const comp = comps[name];

  // ok
  if ('component' in comp) {
    return comp.component;
  }

  // ok
  if ('getComponent' in comp && typeof comp.getComponent === 'function') {
    return comp.getComponent();
  }

  return comp;
}

3.2'de null kontrolleri etkinleştirildiğinde, birliğin tüm üyelerinde eksik olan özellikleri de bildirebilirsiniz, ancak bunları isteğe bağlı olarak ve türü undefined olarak bildirin. Bu, birliğin üzerindeki özelliklere erişmenizi sağlar ve türleri örtüşmediği için Typescript bunu ayırt edici bir birlik olarak kabul eder ve özellikleri kontrol ettiğinizde beklenen tür daralmasını yapar.

type Component = () => {};
type OneType =
  | (Component & { component?: undefined, getComponent?: undefined})
  | { component: Component }
  | { getComponent: () => Component, component?: undefined}

type AnotherType =
  | (Component & { component?: undefined, getComponent?: undefined})
  | ({ // static properties of Component
    option?: string;
    anotherOption?: string;
  } & OneType);

type AnyObject = {
  [name: string]: AnotherType
}

function aFunction(comps: AnyObject, name: string) {
  const comp = comps[name];
{
  if (comp.component) {
    return comp.component;
  }

  if (typeof comp.getComponent === 'function') {
    return comp.getComponent();
  }

  return comp;
}

İlgili makaleler