我的联合类型有问题,如下所示:
type RepeatForm = {
step:
| {
repeat: false;
}
| {
repeat: true;
from: undefined;
}
| {
repeat: true;
from: string;
by?: string;
};
};
我有以下功能,如果它在那里我想获得by
的值:
export const getByField = (form: RepeatForm) => {
if (form.step.repeat === false || form.step.from === undefined) {
return null;
}
const x = form.step.from;
return form.step.by;
};
我收到此错误:Property 'by' does not exist on type '{ repeat: true; from: undefined; } | { repeat: true; from: string; by?: string | undefined; }'.
Property 'by' does not exist on type '{ repeat: true; from: undefined; }'.
这对我来说非常混乱,因为TypeScript知道form.step.from
与undefined
不同,他甚至会将变量类型x
插入到string
。
这个问题的原因是什么?我怎样才能访问by
属性?
答案 0 :(得分:1)
受歧视联盟的原始PR非常具体,因为歧视字段必须是string
字面类型(可选择添加对boolean
和{{1}的支持似乎已经发生的文字类型)。因此,您根据字段类型(number
vs string
)进行区分的用例似乎不受支持。例如,这不起作用:
undefined
我们可以使用条件类型和自定义类型保护来使事情有效:
let u!: { v: number, n: number } | { v: string, s: string}
if(typeof u.v === 'number') {
u.n // not accesible, type not narrowed
}
我们还可以创建此函数的通用版本,允许以任何类型缩小:
function isUndefined<T, K extends keyof T>(value : T, field: K) : value is Extract<T, { [P in K] : undefined }> {
return !!value[field]
}
export const getByField = (form: RepeatForm) => {
if (form.step.repeat === false || isUndefined(form.step, 'from')) {
return null;
}
const x = form.step.from;
return form.step.by;
};