返回void的函数属性名的类型定义

问题描述 投票:0回答:1

我目前正在为我正在进行的项目编写一个小型 RPC 库。为了确保一定程度的正确性,我使用 typescript 进行一些类型检查。我的初始实现工作正常,在进行一些重构时,我遇到了一些条件类型的问题。

想法是沿着下面的接口定义一个 RPC 服务,并能够将返回值(调用)的调用与不返回值(通知)的调用分开。

export default interface ExampleService {
  add(a: number, b: number): number;
  sub(a: number, b: number): number;
  log(message: string): void;
}

到目前为止我正在返回 Promises 并且它工作正常,但是将返回类型切换为文字/无效类型不再正确

type CallMethods<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => void ? never : K;
}[keyof T];

type NotifyMethods<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => void ? K : never;
}[keyof T];

我期待

CallMethods<ExampleServer>
"add" | "sub"
NotifyMethods<ExampleService>
"log"

但是通过这种类型定义,我得到

CallMethods<ExampleService>
never
NotifyMethods<ExampleService>
"add" | "sub" | "notify"
...

我的假设是它与 https://github.com/microsoft/TypeScript/wiki/FAQ#why-are-functions-returning-non-void-assignable-to-function-returning 中解释的可替代性有关-无效

typescript rpc conditional-types
1个回答
0
投票

可以这样写(见playground

export default interface ExampleService {
  add(a: number, b: number): number;
  sub(a: number, b: number): number;
  log(message: string): void;
}

type CallMethods<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => (infer R extends NonNullable<infer Z>) ? K : never;
}[keyof T];

type NotifyMethods<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => (infer R extends NonNullable<infer Z>) ? never : K;
}[keyof T];

type CallMethodsList = CallMethods<ExampleService>;
type NotifyMethodsList = NotifyMethods<ExampleService>;

为了正确检测 void 返回类型,我添加了 NonNullable 检查。这个解决方案的缺点是

null
undefined
的返回类型也将归类为 NotifyMethods 但我现在找不到其他方法。

© www.soinside.com 2019 - 2024. All rights reserved.