带有排除和类型保护的 TypeScript 联合

标签 typescript

为什么下面的代码有错误?

我想知道这是 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在幕后等有同样的问题,它将能够选择所有工会成员共有的工会成员。

您可以获得所需的行为,但不能使用 keyofPick直接地。您需要在带有裸类型参数的条件类型中使用。条件类型将分布在联合的成员中(您可以阅读更多 here 关于此行为或更简洁的版本 here )允许我们应用 keyofPick工会的每个成员,而不是整个工会。

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/

相关文章:

javascript - typescript :使用不同类型的相同类

typescript :导出保存状态的类实例

Angular 4 扩展基础组件

angularjs - Liferay7.0 portlet build with angular and typescript

typescript - 对象数组 Prop 装饰器 StencilJS

javascript - GraphQL + Apollo 错误 : Uncaught (in promise)

typescript - VueJS字符串插值可以访问TS对象的私有(private)属性

angular - RC5 NgModules 声明

javascript - 使用来自 Browserify 和 Typescript 的源映射进行 Webstorm 调试

javascript - 等待 IIFE 结果与单独的异步函数