typescript 获取函数/类构造函数的参数类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43481518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 04:27:45  来源:igfitidea点击:

Get argument types for function / class constructor

typescript

提问by darpa

I am trying to do something I am not sure is possible in TypeScript: inferring the argument types / return types from a function.

我正在尝试做一些我不确定在 TypeScript 中是否可行的事情:从函数推断参数类型/返回类型。

For example

例如

function foo(a: string, b: number) {
  return `${a}, ${b}`;
}

type typeA = <insert magic here> foo; // Somehow, typeA should be string;
type typeB = <insert magic here> foo; // Somehow, typeB should be number;

My use case is to try to create a config object that contains constructors and parameters:

我的用例是尝试创建一个包含构造函数和参数的配置对象:

For example:

例如:

interface IConfigObject<T> {
    // Need a way to compute type U based off of T.
    TypeConstructor: new(a: U): T;
    constructorOptions: U;
}

// In an ideal world, could infer all of this from TypeConstructor

class fizz {
    constructor(a: number) {}
}

const configObj : IConfigObj = {
    TypeConstructor: fizz;
    constructorOptions: 13; // This should be fine
}

const configObj2 : IConfigObj = {
    TypeConstructor: fizz;
    constructorOptions: 'buzz'; // Should be a type error, since fizz takes in a number
}

Can anyone help me out? Thanks!

谁能帮我吗?谢谢!

采纳答案by Markus Mauch

With TypeScript 2.8 you can use the new extendskeyword:

在 TypeScript 2.8 中,您可以使用 newextends关键字:

type FirstArgument<T> = T extends (arg1: infer U, ...args: any[]) => any ? U : any;
type SecondArgument<T> = T extends (arg1: any, arg2: infer U, ...args: any[]) => any ? U : any;

let arg1: FirstArgument<typeof foo>; // string;
let arg2: SecondArgument<typeof foo>; // number;
let ret: ReturnType<typeof foo>; // string;

回答by Matthias

Typescript now has the ConstructorParametersbuiltin, similar to the Parametersbuiltin. Make sure you pass the class type, not the instance:

打字稿现在有ConstructorParameters内置,类似于Parameters内置。确保传递的是类类型,而不是实例:

ConstructorParameters<typeof SomeClass>

回答by dosentmatter

Typescript 2.8 added conditional types with type inference

Typescript 2.8 添加了带有类型推断的条件类型

Typescript 3.0 added rest-elements-in-tuple-types, so you can get all the arguments in an Arraytype now.

Typescript 3.0 添加了rest-elements-in-tuple-types,因此您现在可以获取类型中的所有参数Array

type ArgumentsType<T extends (...args: any[]) => any> = T extends (...args: infer A) => any ? A : never;

type Func = (a: number, b: string) => boolean;
type Args = ArgumentsType<Func> // type Args = [number, string];
type Ret = ReturnType<Func> // type Ret = boolean;

You can use it like this:

你可以这样使用它:

const func = (...args: Args): Ret => { // type the rest parameters and return type
  const [a, b] = args; // spread the arguments into their names
  console.log(a, b); // use the arguments like normal
  return true;
};

// Above is equivalent to:
const func: Func = (a, b) => {
  console.log(a, b);
  return true;
}

回答by Anthony Naddeo

I'll throw in a more direct answer for the use case of extracting the constructor argument types.

对于提取构造函数参数类型的用例,我将给出更直接的答案。

type GetConstructorArgs<T> = T extends new (...args: infer U) => any ? U : never

class Foo {
    constructor(foo: string, bar: number){
        //
    }
}

type FooConstructorArgs = GetConstructorArgs<typeof Foo> // [string, number]

回答by Nitzan Tomer

How about this approach:

这种方法怎么样:

interface IConfigObject<T, U> {
    TypeConstructor: new(a: U) => T;
    constructorOptions: U;
}

class fizz {
    constructor(a: number) {}
}

function createConfig<U, T>(cls: { new (arg: U): T }, arg: U): IConfigObject<T, U> {
    return {
        TypeConstructor: cls,
        constructorOptions: arg
    }
}

const configObj = createConfig(fizz, 3); // ok
const configObj2 = createConfig(fizz, "str"); // error

(code in playground)

操场上的代码



Edit

编辑

You can have an indexed type variable:

你可以有一个索引类型变量:

const configs: { [name: string]: IConfigObject<any, any> } = {
    config1: createConfig(fizz, 3),
    config2: createConfig(fizz, "str"), // error
    config3: createConfig(buzz, "str")
}