首页 文章

Typescript无法检查函数类型和对象类型的并集中的属性

提问于
浏览
1

Typescript无法检查函数类型的联合中的属性以及使用另一个对象和函数联合拦截的对象类型 .

这是重现问题的最小回购 . 存档的正确方法是什么?

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;
}

这是Playgroud:Playground repo

1 回答

  • 2

    Typescript只允许您访问联合中的公共属性 . 一种解决方案是使用 in type-guard来说服编译器你正在谈论的工会成员 .

    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中,您还可以在union的所有成员上声明缺少的属性,但是将它们声明为可选,如果键入 undefined . 这将允许您访问union上的属性,并且由于它们的类型不重叠,因此,Typescript会将其视为一个有区别的并集,并在检查属性时执行预期的类型缩小 .

    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;
    }
    

相关问题