【发布时间】:2022-03-02 11:39:06
【问题描述】:
ReturnType<T> 提取函数的返回类型。
有没有办法定义ArgumentsType<T>,以tuple 格式提取函数的参数类型?
例如,
ArgumentsType<(a: number, b: string) => boolean> 将是 [number, string]。
【问题讨论】:
标签: typescript
ReturnType<T> 提取函数的返回类型。
有没有办法定义ArgumentsType<T>,以tuple 格式提取函数的参数类型?
例如,
ArgumentsType<(a: number, b: string) => boolean> 将是 [number, string]。
【问题讨论】:
标签: typescript
编辑
自从写出原始答案以来,typescript 现在有一个内置类型(在lib.d.ts 中定义)来获取名为Parameters 的参数类型
type argsEmpty = Parameters<() => void> // []
type args = Parameters<(x: number, y: string, z: boolean) => void> // [number, string, boolean]
type argsOpt = Parameters<(x: number, y?: string, z?: boolean) => void> // [number, (string | undefined)?, (boolean | undefined)?]
编辑 Typescript 3.0 已发布,以下代码按预期工作。
虽然在当前版本的 typescript (2.9) 中,如果不拼写所有参数,这是不可能的。这将在未来几天发布的下一版 typescript (3.0) 中成为可能:
type ArgumentsType<T> = T extends (...args: infer U) => any ? U: never;
type argsEmpty = ArgumentsType<() => void> // []
type args = ArgumentsType<(x: number, y: string, z: boolean) => void> // [number, string, boolean]
type argsOpt = ArgumentsType<(x: number, y?: string, z?: boolean) => void> // [number, (string | undefined)?, (boolean | undefined)?]
如果您安装了npm install typescript@next,您已经可以使用它,它应该在本月的某个时候可用。
注意
我们还可以使用这个新功能将元组传播到参数中:
type Spread<T extends any[]> = (...args: T)=> void;
type Func = Spread<args> //(x: number, y: string, z: boolean) => void
您可以阅读有关此功能的更多信息here
【讨论】:
Parameters? This 应该更清楚
Parameters<ClassName['methodName']> 不要忘记为有用的答案投票;)
b(param: Parameters<myClass['a']> [0]) 或 b(param: Parameters<this['a']> [0]) 为例(但我通常会避免多态。
从 TypeScript 3.1 开始,Parameters 类型现在是标准库的一部分。
type Result = Parameters<(a: number, b: string) => boolean>; // [number, string]
【讨论】:
目前无法为任何可能的函数同时提取类型和数量的参数。但是你可以试试这样的:
type ArgumentTypes<T> = T extends () => any ? never[] :
T extends (a1: infer T1) => any ? [T1] :
T extends (a1: infer T1, a2: infer T2) => any ? [T1, T2] :
// continue here for any reasonable number of args
never;
通过以下方式检查:
const args0: ArgumentTypes<() => boolean> = []; // correct
const args1: ArgumentTypes<(a: number) => boolean> = [1]; // correct
const args2: ArgumentTypes<(a: number, b: string) => boolean> = [1, 'str']; // correct
const oops0null: ArgumentTypes<() => boolean> = null; // error, arguments are array (but empty one)
const oops01: ArgumentTypes<() => boolean> = [1]; // error, arguments must be empty
const oops10: ArgumentTypes<(a: number) => boolean> = []; // error, we need one argument
const oops12: ArgumentTypes<(a: number) => boolean> = [1, 2]; // error, we need only one argument
const oops1wrong: ArgumentTypes<(a: number) => boolean> = ['str']; // error, argument must be number
const oops21: ArgumentTypes<(a: number, b: string) => boolean> = [1]; // error, we need two arguments
const oops23: ArgumentTypes<(a: number, b: string) => boolean> = [1, 'str', undefined]; // error, we need only two arguments
const oops2wrong: ArgumentTypes<(a: number, b: string) => boolean> = ['str', 1]; // error, arguments are reversed
请注意,这不使用任何可选参数 - 它们只是从输出中省略。我暂时无法找到捕捉它们的方法。
【讨论】:
对于我的问题,我使用了以下样式:
const myFunction = <T>(items: T[], config: FuseConfigType) => {
const fuse = new Fuse(items, config);
return (pattern: string): T[] =>
pattern === '' ? items : fuse.search(pattern).map(({ item }) => item);
};
export default fuseSearch;
我得到 T 类型,即 items 中每个项目的类型,然后当我想返回函数时,我使用 T 传递它,就像我得到它一样。
【讨论】:
我创建了一组常见的辅助类型,如下所示:https://github.com/joonhocho/tsdef
您可以在这里找到许多打字稿的辅助模式。
你也可以通过 npm 或 yarn 安装。
npm i -D tsdef
【讨论】:
我确信Parameters<T> 有很多用途,但我想要一种方法来为私有成员上的相同方法提供代理方法,这似乎非常合适。
例如。我想要以下内容,这样如果authService.login 签名发生更改,我就不必修改我的代理——只要调用它。
login(username: string, password: string) { this.authService.login(username, password); }
使用Parameters<T>,您可以执行以下操作
login = (...params: Parameters<AuthService['login']>) => this.authService.login(...params);
当然,好处是如果你有复杂的参数,它会很好地照顾自己 - (可能不会只为两个字符串推荐这个!)
我尝试了几次才发现我在两次出现 params 时都需要 ...。
【讨论】:
扩展@Titian Cernicova-Dragomir's answer,如果您使用命名函数表达式,因此无法定义类型,您可以使用typeof 访问参数,如下所示:
function updateTable<T extends IHasOBJECT_ID>(
diff: Diff,
cache: { [id: string]: Table<T, Array<keyof T>> & IHasOBJECT_ID & IHasCONFLICTS & IHasOPTIONS },
) {
// Use typeof to get the parameter type for cache
const cacheItem: Parameters<typeof updateTable>[1] = cache[diff.id];
// ...
}
【讨论】:
如果函数参数在 class 上,那么您可以使用以下方法来提取它们:
class Foo {
bar(a: string, b: number) {
// Want these ^
}
}
type BarFn = Foo['bar'];
// ^ (a: string, b: number) => void
type BarFnArguments = Parameters<BarFn>;
// ^ [string, number]
type FirstArg = BarFnArguments[0]
// ^ string
type SecondArg = BarFnArguments[1]
// ^ number
对于单元测试模拟很有用,有时可以用玩笑对其进行无类型化。
【讨论】: