TypeScript 条件排除类型从接口中排除

Fur*_*man 1 typescript typescript-typings

根据文档,我可以使用预定义的排除类型从某些类型中排除某些属性:

type Test = string | number | (() => void);

type T02 = Exclude<Test, Function>;
Run Code Online (Sandbox Code Playgroud)

但是,如果我有 Test 接口而不是 Test 类型,它似乎不起作用。如何在以下情况下获得类似的结果?

interface Test {
  a: string;
  b: number;
  c: () => void;
} 

// get somehow interface with excluded function properties??
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 8

要获得这种效果,您需要弄清楚哪些属性匹配Function,然后有选择地排除它们。等效地,我们找到哪些属性不匹配Function,然后有选择地包含它们。这不仅仅是排除联合的某些部分更复杂;它涉及映射类型条件类型

一种方法如下:

type ExcludeMatchingProperties<T, V> = Pick<
  T,
  { [K in keyof T]-?: T[K] extends V ? never : K }[keyof T]
>;

type T02 = ExcludeMatchingProperties<Test, Function>;
// type T02 = {
// a: string;
// b: number;
// }
Run Code Online (Sandbox Code Playgroud)

通过检查ExcludeMatchingProperties<T, V>,我们可以注意到该类型{ [K in keyof T]-?: T[K] extends V ? never : K }[keyof T]将返回T其属性不可分配给的键V

如果TTestVFunction,这将变成类似

{ 
  a: string extends Function ? never : "a"; 
  b: number extends Function ? never : "b"; 
  c: ()=>void extends Function ? never : "c" 
}["a"|"b"|"c"]
Run Code Online (Sandbox Code Playgroud)

,这变成

{ a: "a"; b: "b"; c: never }["a"|"b"|"c"]
Run Code Online (Sandbox Code Playgroud)

,这变成

{ a: "a"; b: "b"; c: never }["a"] | 
{ a: "a"; b: "b"; c: never }["b"] | 
{ a: "a"; b: "b"; c: never }["c"]
Run Code Online (Sandbox Code Playgroud)

, 或者

"a" | "b" | never
Run Code Online (Sandbox Code Playgroud)

, 或者

"a" | "b"
Run Code Online (Sandbox Code Playgroud)

一旦我们有了这些键,我们就可以将Pick它们的属性从T(使用Pick<T, K> 实用程序类型):

Pick<Test, "a" | "b">
Run Code Online (Sandbox Code Playgroud)

这成为所需的类型

{
  a: string,
  b: number
}
Run Code Online (Sandbox Code Playgroud)

好的,希望有帮助;祝你好运!

代码链接