Typescript在函数类型和对象类型的并集中检查属性失败



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

这是游乐场:游乐场回购

Typescript只允许您访问联合中的公共属性。一种解决方案是使用in类型保护来说服编译器您正在谈论的联合的哪个成员。

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

在启用了null检查的3.2中,您还可以声明联合的所有成员上缺少的属性,但如果类型为undefined,则将它们声明为可选属性。这将允许您访问并集上的属性,并且由于它们的类型不重叠,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;
}

最新更新