为什么下面的代码有错误?
我想知道这是TypeScript编译器的错误。
type A =
| {
type: 'a';
a: string;
}
| {
type: 'b';
b: string;
};
type X = {
x: string;
} & A;
type XX = Pick<X, Exclude<keyof X, 'x'>> & {
x: number;
};
const x: XX = {} as any;
if (x.type === 'a') {
// Property 'a' does not exist on type 'XX'
console.log(x.a);
}
答案 0 :(得分:1)
您看到的只是联合类型如何工作的结果。联合(除非缩小)仅允许访问公共属性。因此,当您说keyof X
时,将在结果字符串文字联合中出现的唯一属性是x
(不依赖于联合)和type
,这两个联合成员都共有。 Pick
在后台也使用keyof
,因此存在相同的问题,它将能够选择所有工会成员共有的工会成员。
您可以得到所需的行为,但不能直接使用keyof
和Pick
。您需要在带裸类型参数的条件类型中使用。条件类型将分布在工会的成员上(您可以了解更多关于此行为的here或更简洁的版本here),从而使我们可以在每个成员上应用keyof
和Pick
工会成员,而不是整个工会。
type A =
| {
type: 'a';
a: string;
}
| {
type: 'b';
b: string;
};
type X = {
x: string;
} & A;
type UnionKeys<T> = T extends any ? keyof T : never;
type UnionPick<T, K extends UnionKeys<T>> = T extends any ? Pick<T, Extract<K, keyof T>> : never
type XX = UnionPick<X, Exclude<UnionKeys<X>, 'x'>> & {
x: number;
};
const x: XX = {} as any;
if (x.type === 'a') {
console.log(x.a);
}