【发布时间】:2021-02-20 02:42:28
【问题描述】:
我想定义一个“执行”方法,该方法根据其参数返回同步或异步结果:
type Callback = (...args: Arguments) => Result
const result: Result = execute(callback: Callback, args: Arguments)
type Callback = (...args: Arguments) => Promise<Result>
const result: Promise<Result> = execute(callback: Callback, args: Arguments)
type Callback = (...args: Arguments) => Result | Promise<Result>
const result: Promise<Result> = execute(callback: Callback, args: Promise<Arguments>)
我尝试这个没有成功:
console.clear()
type Callback<Arguments extends Array<any>, Result> =
| ((...args: Arguments) => Result)
| ((...args: Arguments) => Promise<Result>)
const execute = <Arguments extends Array<any>, Result> (callback: Callback<Arguments, Result>, args: Arguments | Promise<Arguments>): typeof args extends Promise<Arguments> ? Promise<Result> : ReturnType<typeof callback> => {
if (args instanceof Promise) {
return args.then(resolved_args => {
const result = callback(...resolved_args)
return result
})
}
else {
return callback(...((args ?? []) as Arguments))
}
}
const async_demo = async (value: number) => {
const a = await Promise.resolve(1)
return a + value
}
const sync_demo = (value: number) => 1 + value
type SyncDemoResult = ReturnType<typeof sync_demo>
const result_1: number = execute(sync_demo, [1])
const result_2: Promise<number> = execute(sync_demo, Promise.resolve([1] as [number]))
const result_3: Promise<number> = execute(async_demo, [1])
const result_4: Promise<number> = execute(async_demo, [1])
有可能吗?
【问题讨论】:
-
我对 TypeScript 的了解不够深入,无法知道它是否可能,但即使它可能也是可取的吗?有时是同步的,有时是异步的函数并不是一个好主意,而且肯定需要你在 TypeScript 中破坏类型安全才能尝试它。我建议您使用
executeAsync()进行异步操作。 -
使用这种技术,我可以在数据访问(DDD 中的存储库)同步或异步的客户端代码(同步)和服务器(异步)之间共享业务代码。通过使用“执行”注入存储库,我可以获得在客户端同步和在服务器上异步的方法。 Promise 在性能上的成本太高,而且有时在 React 应用程序中使用钩子会更复杂。
-
但是,如果您的代码只是在 API 下方和 API 上方进行分支以处理异步和同步情况,并且您只是通过非类型化和非描述性的单一 API 填充所有内容,我不会看不到你得到了什么。如果根据同步和异步进行拆分,您仍然可以共享同样多的代码。我认为您为了完美的代码共享而扭曲了 API 的设计和使用。 IMO,这是错误的优先顺序。应优先考虑设计、使用和维护的清洁度。
-
函数式编程的神奇之处:“执行”方法是currified,用于包装存储库访问:因此我可以创建在客户端(同步/存储)和服务器(异步)之间共享的业务方法/ 数据库)。我注入存储库访问方法来构建客户端或服务器代码。相同的代码,2 个签名,取决于注入的方法。 ;-)
标签: typescript asynchronous promise type-inference