Typescript:更改函数类型,使其返回新值 [英] Typescript: change function type so that it returns new value

查看:168
本文介绍了Typescript:更改函数类型,使其返回新值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我想要这样的东西:

Basically, I want something like this:

export type ReturnValueMapper<Func extends (...args: Args[] /* impossible */ ) => any, ReturnValue> = (...args: Args[]) => ReturnValue;

我几乎确定这是不可能的,但是我没有找到确切的确认信息.

I'm almost sure that it's impossible, but I haven't found exact confirmation.

该用例正在改进 recompose的withStateHandlers ,这样就可以定义状态更新程序:

The use case is improving types for recompose's withStateHandlers, enabling defining state updaters like this:

interface StateUpdaters {
    update(field: string): void; // I don't want to specify Partial<State> here 
}

推荐答案

编辑

自从回答了原始问题以来,打字稿已经改善了该问题的可能解决方案.通过添加在其余参数和扩展表达式中添加,我们现在不需要有所有的重载:

Since the original question was answered typescript has improved the possible solution to this problem. With the addition of Tuples in rest parameters and spread expressions we now don't need to have all the overloads:

type ReplaceReturnType<T extends (...a: any) => any, TNewReturn> = (...a: Parameters<T>) => TNewReturn;

这不仅更短,而且还解决了许多问题

Not only is this shorter but it solves a number of problems

  • 可选参数保持可选状态
  • 保留参数名称
  • 适用于任意数量的参数

示例:

type WithOptional = ReplaceReturnType<(n?: number)=> string, Promise<string>>;
let x!: WithOptional; // Typed as (n?: number) => Promise<string>
x() // Valid
x(1); //Ok

原始

Original

要获得良好的解决方案,您将需要变量类型,但现在,此 answer 提供了可行的解决方案. (将其作为此处的类型发布在此处,作为对其他问题的解决方案的一部分.)

For a good solution you will need variadic types, but for now this answer provides a workable solution. (Posting it here as the type there is used as part of a solution to a different question).

基本思想是我们将提取参数类型,并使用新的返回类型重新构造函数签名.这种方法有几个缺点:

The basic idea is that we will extract the parameter types and recompose the function signature with the new return type. There are several disadvantages to this approach:

  1. 不保留参数名称
  2. 可选参数处理不正确
  3. 仅适用于特定数量的参数(但可以根据需要添加更多参数)

可能还有其他问题,但是根据您的用例,这可能是一个足够好的解决方案,直到类型系统解决该用例为止.

There may be other issues, but depending on your use-case this may be a good enough solution until the type system addresses this use case.

type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type ReplaceReturnType<T, TNewReturn> = T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => infer R ? (
    IsValidArg<J> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => TNewReturn :
    IsValidArg<I> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => TNewReturn :
    IsValidArg<H> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => TNewReturn :
    IsValidArg<G> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => TNewReturn :
    IsValidArg<F> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F) => TNewReturn :
    IsValidArg<E> extends true ? (a: A, b: B, c: C, d: D, e: E) => TNewReturn :
    IsValidArg<D> extends true ? (a: A, b: B, c: C, d: D) => TNewReturn :
    IsValidArg<C> extends true ? (a: A, b: B, c: C) => TNewReturn :
    IsValidArg<B> extends true ? (a: A, b: B) => TNewReturn :
    IsValidArg<A> extends true ? (a: A) => TNewReturn :
    () => TNewReturn
) : never


与可选参数一起使用时,问题在于可选参数成为必需参数(且为type A | undefined):

type WithOptional = ReplaceReturnType<(n?: number)=> string, Promise<string>>;

let x!: WithOptional;
x(); //invalid
x(undefined);
x(1);

这篇关于Typescript:更改函数类型,使其返回新值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆