我有一个简单的api调用函数,该函数可获取数据并根据参数标志有条件地映射结果。
作为获取结果,我得到的是条件类型或联合类型,但是我不能在这里使用类型保护,因为这两种类型不共享公共的可区分属性,因此我应该对其进行区分基于外部类型。我怎样才能告诉打字稿这两种类型取决于另一种类型?是否需要添加另一层间接寻址?
public static Spanned stripHtml(String html) {
if (!TextUtils.isEmpty(html)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT);
} else {
return Html.fromHtml(html);
}
}
return null;
}
我能够使用它来进行类型转换,并通过函数调用获得正确的返回类型,但这很麻烦,我认为这不是正确的方法
text_view.setText(stripHtml(htmlText));
为条件类型添加类型别名有助于摆脱缺少呼叫签名错误的问题,但我却得到了不匹配的类型错误
// prerequisites
declare function apiService(...a: any[]): any;
declare function mapExternalFoo(x: IExternalFoo): IFoo;
declare function mapExternalBar(x: IExternalBar): IBar;
interface IFoo { a: any; }
interface IBar { b: any; }
interface IExternalFoo { c: any; }
interface IExternalBar { d: any; }
interface IProps<T extends boolean> {
isExtended?: T;
}
// I want it to look like this, but it fails with a compile error
function fetchData<T extends boolean>(params: IProps<T>): Promise<T extends true ? IFoo : IBar> {
return apiService('/user/data', params).then(
(data: T extends true ? IExternalFoo[] : IExternalBar[]) =>
// Cannot invoke an expression whose type lacks a call signature.
params.isExtended ? data.map(mapExternalFoo) : data.map(mapExternalBar)
);
}
答案 0 :(得分:3)
TypeScript并未真正将其控制流分析分布在并集类型上,并且对条件类型的处理甚至更少。在类似I wish的时候,您可以告诉编译器手动遍历表达式的某些可能范围,并且仅当所有此类范围均被视为类型安全时,才能成功。 this,这不存在,很难说这种痛点在可预见的将来是否会变得更好。
鉴于这种不幸的情况,最直接的处理方法可能是在函数实现内使用类型声明(如data as IExternalFoo[]
),以及函数签名上的重载(您只需要一个带条件类型的重载签名)。 ..和一个带有工会的实施签名)。这几乎就是您所做的,因此,除了“在这种情况下我也是这么做的”之外,我没有其他建议。条件类型对函数调用者比对函数实现者有用。
所以我唯一的建议是您可以将条件类型保留在重载签名中:
function fetchData<T extends boolean>(params: IProps<T>): Promise<T extends true ? IFoo[] : IBar[]>;
function fetchData(params: IProps<boolean>): Promise<IFoo[] | IBar[]> {
return apiService('/user/data', params)
.then(
(data: IExternalFoo[] | IExternalBar[]) =>
params.isExtended
? (data as IExternalFoo[]).map(mapExternalFoo)
: (data as IExternalBar[]).map(mapExternalBar)
);
}
const promseIFooArray = fetchData({isExtended: true});
const promseIBarArray = fetchData({isExtended: false});
const promiseEitherArray = fetchData({isExtended: Math.random()<0.5});
哦,希望能有所帮助。祝你好运!