Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.6k views
in Technique[技术] by (71.8m points)

typescript - 如何在TypeScript中将函数类型转换为其异步等效项?(How do you turn a function type into its async equivalent in TypeScript?)

How can I type this function in relation to its input fn ?

(如何相对于输入fn键入此函数?)

function makeAsync(fn) {
  return async (...args) => fn(...args);
}

It returns a function identical to its input, but instead of returning Type it would return Promise<Type>

(它返回与输入相同的函数,但不返回Type而是返回Promise<Type>)

Usage example:

(用法示例:)

const a = () => 1; // Type () => number;
const b = makeAsync(a); // Type () => Promise<number>;
const c = makeAsync(b); // Type () => Promise<number>; // ?, not Promise<Promise<number>>

This works, but it's a little verbose

(可以,但是有点冗长)

// Unwraps a Promise<T> value into just T, so we never get Promise<Promise<T>>
type Unpromise<MaybePromise> = MaybePromise extends Promise<infer Type> ? Type : MaybePromise;

// Like ReturnType, except it returns the unwrapped promise also for async functions
type AsyncReturnType<T extends (...args: any[]) => any> = Unpromise<ReturnType<T>>

// For a `() => T` function it returns its async equivalent `() => Promise<T>`
type PromisedFunction<T extends (...args: any[]) => any> =
    (...args: Parameters<T>) => Promise<AsyncReturnType<T>>;
function makeAsync<T extends (...args: any[]) => any>(fn: T): PromisedFunction<T> {
  return async (...args) => fn(...args);
}

TypeScript Playground link

(TypeScript游乐场链接)

Are there any better/shorter ways to achieve this?

(有没有更好/更短的方法来实现这一目标?)

  ask by fregante translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can shorten up the types a bit by defining separate type parameters A , R for the function parameters and return type, so they are inferred automatically.

(您可以通过为函数参数和返回类型定义单独的类型参数AR来稍微缩短类型,以便自动推断它们。)

Then it is easy to just wrap a Promise around R in makeAsync2 ( sample ):

(然后,很容易将Promise包裹在makeAsync2样本 )中的R周围:)

declare function makeAsync2<A extends any[], R>(fn: (...args: A) => R): (...args: A) => Promise<R>

const c = (arg1: number, arg2: string[]) => 1; // (arg1: number, arg2: string) => number
const d = makeAsync2(c); // (arg1: number, arg2: string[]) => Promise<number>
const cResult = c(3, ["s"]) // number
const dResult = d(3, ["s"]) // Promise<number>

Edit:

(编辑:)

If the input function potentially can itself return a promise, we can flatten the return type of makeAsync2 , so promises don't get nested ( sample ):

(如果输入函数本身可能会返回一个promise,我们可以将makeAsync2的返回类型展平,因此promise不会被嵌套( sample ):)

// this works for a single nested promise
type FlattenPromise<T> = T extends Promise<any> ? T : Promise<T>

declare function makeAsync2<A extends any[], R>(fn: (...args: A) => R): (...args: A) => FlattenPromise<R>

const e = (arg1: string) => Promise.resolve(3) // (arg1: string) => Promise<number>
const f = makeAsync2(e); // (arg1: string) => Promise<number>
const eResult = e("foo") // Promise<number>
const fResult = f("foo") // Promise<number>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...