以下代码:
// 联合类型
type TBool = {
success: Extract<boolean, true>;
} | {
success: Extract<boolean, false>;
error: number;
}
// 将特定字段转换为非必填
type WithoutId<T> = Omit<T, 'id'> & {id?: string};
// 类型定义
type Demo = {
id: string;
} & TBool;
// 这个用法下无法基于success是false进一步推断
const data: WithoutId<Demo> = {
success: false,
error: 500, // error不在类型WithoutId<Demo>中
}
// 但是不使用WithoutId就正常了
const idData: Demo = {
id: '5',
success: false,
error: 500,
}
是WithoutId的问题吗?还是我对联合类型的用法理解上有问题?typescript 4.5.5
感谢楼下的回答,通过以下的方式可以实现了。
type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
// 联合类型
type TBool = {
success: Extract<boolean, true>;
} | {
success: Extract<boolean, false>;
error: number;
}
// 将特定字段转换为非必填
type WithoutId<T> = DistributiveOmit<T, 'id'> & {id?: string};
// 类型定义
type Demo = {
id: string;
} & TBool;
// 现在正常了
const data: WithoutId<Demo> = {
success: false,
error: 500,
}
const data2: WithoutId<Demo> = {
success: true,
}
问题应该出在
Omit
类型声明这步,对于TBool
这个联合类型,Omit
取到的key
是联合类型的最小交集,不包含error
字段。可能只能间接实现了,可以参照 https://stackoverflow.com/questions/57103834/typescript-omit-a-property-from-all-interfaces-in-a-union-but-keep-the-union-s