如何推断泛型函数的返回类型

时间:2019-11-27 14:28:37

标签: typescript typescript-generics

我有一个始终返回一个类型的函数,尽管它可以更改,并且手动定义它是一项工作且无法扩展,所以我试图通过使用typescript的infer关键字来实现这一点

起初我看到this reddit post 使用

type Foo<T> = T extends { a: infer U, b: infer U } ? U : never;
type T10 = Foo<{ a: string, b: string }>;  // string
type T11 = Foo<{ a: string, b: number }>;  // string | number

问题是,我的类型是通用函数

这是一个最小的示例,

const fnFromLib = <T>(a: string, b: Record<string, string>) => {
  return function barFn(c: T) {
    return {
      c,
      b: b[a],
    };
  };
};
const foo = <T>(a: Record<string, string>) => {
  return {
    bar: fnFromLib<T>('foo', a),
  };
};
type returnTypeInferer<T> = T extends (a: Record<string, string>) => infer U ? U : never;
type fooType = typeof foo;
type fooReturnType = returnTypeInferer<fooType>;

没有错误,但是由于没有传递通用类型,因此fooReturnType将被推断为

type fooReturnType = {
    bar: (c: unknown) => {
        c: unknown;
        b: string;
    };
}

注意到fnFromLib的T不是从参数推断的,应该在函数调用中传递,我尝试将类型参数从fooReturnType传递到fooType,但这给了我一个解析错误< / p>

type returnTypeInferer<T> = T extends (a: Record<string, string>) => infer U ? U : never;
type fooType<T> = typeof foo<T>; // ------   parsing error: ';' expected ---------
type fooReturnType<T> = returnTypeInferer<fooType<T>>;

有什么方法可以实现我想要的?

谢谢

1 个答案:

答案 0 :(得分:1)

通过将函数包装到通用类中来做到这一点

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Music_Test {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Music_Test window = new Music_Test();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Music_Test() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        JPanel Menu = new JPanel();
        Menu.setBounds(6, 6, 438, 266);
        frame.getContentPane().add(Menu);
        Menu.setLayout(null);
        Menu.setVisible(true);

        JPanel Select_Level = new JPanel();
        Select_Level.setBounds(6, 6, 438, 266);
        frame.getContentPane().add(Select_Level);
        Select_Level.setVisible(false);

        JButton btnSelectLevel = new JButton("Select Level");
        btnSelectLevel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Menu.setVisible(false);
                Select_Level.setVisible(true);
            }
        });
        btnSelectLevel.setBounds(158, 45, 117, 29);
        Menu.add(btnSelectLevel);

        JLabel lblMenu = new JLabel("Menu");
        lblMenu.setFont(new Font("Comic Sans MS", Font.BOLD, 22));
        lblMenu.setBounds(187, 17, 61, 29);
        Menu.add(lblMenu);

        JLabel lblSelectLevel = new JLabel("Select Level");
        lblSelectLevel.setFont(new Font("Comic Sans MS", Font.BOLD, 22));
        lblSelectLevel.setBounds(187, 17, 61, 29);
        Select_Level.add(lblSelectLevel);


    }
}

但是我想坚持使用函数式编程,我不会将其标记为可接受的答案,因为我目前看不到其他选择,所以会暂时使用它,并且会喜欢另一种方法。