为什么下面的代码有错误?
我想知道这是 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);
}
You can try this code on TypeScript Playground
最佳答案
您所看到的只是联合类型如何工作的结果。联合(除非缩小)只允许访问公共(public)属性。所以当你说 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);
}
关于带有排除和类型保护的 TypeScript 联合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53945567/