我正在try 编写一种类型,该类型通过值为函数但不是Promise函数的键来过滤对象.

我如何才能确保type keys只返回"A",因为B返回promise ,因此应该被排除在外?

type FilterKeys<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];

type O = {
  A: () => void;
  B: () => Promise<void>;
};

// type keys = "A" | "B"
// WANT: type keys = "A"
type keys = FilterKeys<O, (e: never) => void>;

// type keys2 = "B"
// OK
type keys2 = FilterKeys<O, (e: never) => Promise<void>>;

推荐答案

您的FilterKeys<T, U>的行为类似于the Extract utility type,因为它 Select 可以分配给另一种类型的东西.您可以通过 Select 可将not分配给另一类型的对象来获得所需的行为,使其行为类似于the Exclude utility type.只需切换相关conditional type的真和假分支:

type ExcludeKeys<T, U> = {
  [K in keyof T]: T[K] extends U ? never : K;
}[keyof T];

然后,您可以将ExcludeKeys() => Promise<unknown>一起使用,以仅获取其值不是Promise返回函数的键:

type O = {
  A: () => void;
  B: () => Promise<string>;
};

type Keys = ExcludeKeys<O, () => Promise<unknown>>;
//   ^? type Keys = "A"

请注意,() => Promise<unknown>() => Promise<void>更宽,因此将捕获所有返回Promise的函数.


当然,这也将为您提供非函数,因此,如果您需要保留值类型为不返回promise 的函数的only个键,您将需要两个过滤器的组合:

type ExtractKeys<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
    
type O = {
  A: () => void;
  B: () => Promise<void>;
  C: string // we don't want this one either
};

type Keys = ExcludeKeys<Pick<O, ExtractKeys<O, Function>>, () => Promise<unknown>>;
//   ^? type Keys = "A"

或者,您可以构建一个组合过滤器:

type ExtractExcludeKeys<T, Y, N> = {
  [K in keyof T]: T[K] extends N ? never : T[K] extends Y ? K : never;
}[keyof T]

type Keys = ExtractExcludeKeys<O, Function, () => Promise<unknown>>;
//   ^? type Keys = "A"

Playground link to code

Typescript相关问答推荐

如何使用属性作为具有Generics的TypScript类中的类型守护?

我用相同的Redux—Toolkit查询同时呈现两个不同的组件,但使用不同的参数

异步动态生成Playwright测试,显示未找到测试

打印脚本丢失函数的泛型上下文

如何在TypeScrip中使用嵌套对象中的类型映射?

是否有一个版本的联合类型递归地使属性只出现在一个可选选项中?

ANGLING v17 CLI默认设置为独立:延迟加载是否仍需要@NgModule进行路由?

如果数组使用Reaction-Hook-Form更改,则重新呈现表单

在列表的指令中使用intersectionObservable隐藏按钮

如何在Vue中使用Enum作为传递属性的键类型?

如何从MAT-FORM-FIELD-MAT-SELECT中移除焦点?

创建Angular 为17的动态形状时出错

如何创建由空格连接的多个字符串的类型

在正常函数内部调用异步函数

如何解决&Quot;类型不可分配给TypeScrip IF语句中的类型&Quot;?

如何将通用接口的键正确设置为接口的键

带有';的类型脚本嵌套对象可选属性错误满足';

如何从抽象类的静态方法创建子类的实例?

TypeScript:如何使用泛型和子类型创建泛型默认函数?

两个接口的TypeScript并集,其中一个是可选的