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

dar*_*rpa 21 typescript

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

例如

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;
Run Code Online (Sandbox Code Playgroud)

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

例如:

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
}
Run Code Online (Sandbox Code Playgroud)

谁能帮我吗?谢谢!

Mar*_*uch 20

使用TypeScript 2.8,您可以使用new extends关键字:

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;
Run Code Online (Sandbox Code Playgroud)


dos*_*ter 8

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

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;
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

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;
}
Run Code Online (Sandbox Code Playgroud)


Ant*_*deo 8

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

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]
Run Code Online (Sandbox Code Playgroud)


Mat*_*ley 7

Typescript现在具有ConstructorParameters内置功能,类似于Parameters内置功能。确保您传递类类型,而不是实例:

ConstructorParameters<typeof SomeClass>
Run Code Online (Sandbox Code Playgroud)

  • 效果很好!如果 SomeClass 的构造函数接受一个对象作为第一个参数,则获取该对象类型的语法将是 `ConstructorParameters&lt;typeof SomeClass&gt;[0]` (13认同)
  • 但是如果我们在“SomeClass”上有一个通用参数呢?我尝试了 `ConstructorParameters&lt;typeof SomeClass&lt;T&gt;&gt;` 但事实证明它不是有效的语法。 (6认同)