有什么方法可以 "spread" 对象属性到函数定义的参数吗?
Is there some way to "spread" object properties to parameters of a function definition?
最好用代码解释:
const ROUTE_PARAMS = {
userId: 'userId',
companyId: 'companyId',
};
// Is this somehow possible?
// `typeof` is obviously not the right tool here, just used as an example.
function buildRoute(typeof ROUTE_PARAMS): string;
// Result should be similar to:
function buildRoute2(userId: string, companyId: string): string;
// The function should be called like this:
buildRoute('some-user-id', 'some-company-id');
// I don't want the function to accept only 1 object like this:
buildRoute({ userId: 'some-user-id', companyId: 'some-company-id' });
想法是让 buildRoute
的路由参数以某种方式动态“绑定”到对象。
当“手动”定义函数参数时(如 buildRoute2
),我总是必须在更改 ROUTE_PARAMS
...
的属性时使它们保持同步
附加信息
我会尝试添加一些信息,因为我上面的问题似乎不够清楚:
- 我正在明确地寻找一种从 对象 中“输入”此函数的方法,如上所示 (
ROUTE_PARAMS
)。
- 我无法将其更改为其他结构(元组类型、某种数组...),因为这需要重构代码中与对象
ROUTE_PARAMS
一起使用的其他部分。
- 该函数应将每个对象 属性 作为单个输入参数(即函数 arity === 对象属性的数量)除外。
我不希望函数接受打包到 1 个对象中的所有属性(& 上面的示例)。
起初,我认为通过使用元组类型的展开运算符可以轻松实现您想要的结果。例如,
function f(...args: [string, string]) {}
与
相同(参数名称除外)
function f(arg0: string, arg1: string) {}
所以我们可以尝试:
const ROUTE_PARAMS = {
userId: 'userId',
companyId: 'companyId',
};
function buildRoute(...args: typeof ROUTE_PARAMS[keyof typeof ROUTE_PARAMS][]): void {}
然而,typeof ROUTE_PARAMS[keyof typeof ROUTE_PARAMS][]
是一个数组,因此我们可以为生成的 buildRoute
函数提供任意数量的参数。它实际上与您编写 function buildRoute(...args: string[])
时相同。此外,当值不仅是 string
s,而且例如包含 number
时,推断类型将是 (string | number)[]
并且我们可以在以下位置提供 number
任意位置。
与上面 f
的不同之处在于,传播变量的类型是 tuple for f
但 array 对于 buildRoute
。所以我们需要从 ROUTE_PARAMS
的值中得到一个元组。但是,不幸的是,这不受支持,也不会得到支持,因为相应的提议被拒绝了:https://github.com/microsoft/TypeScript/issues/13298.
所以我现在认为您想要的可能无法通过 TypeScript 实现。
更新答案:
如 中所述,不支持将函数参数扩展到变量的一组特定属性和类型。 Remirrors 的回答很好地解释了为什么会这样。
但是,只是为了扩展 Remirrors 答案以使语法更清晰一些,您可以创建一个使用泛型的全局类型。然后可以在您需要的所有地方重复使用,而无需重复重写长 keyof 代码:
// Re-useable type
export type TypeFromVar<T> = T[keyof T][];
const ROUTE_PARAMS = {
userId: 'userId',
companyId: 'companyId',
};
const User = {
name: 'Reece',
age: 25,
isVerified: true,
}
function buildRoute(...routes: TypeFromVar<typeof ROUTE_PARAMS>) {
const [userId, companyId] = args;
// do something
}
function otherFunction(...person: TypeFromVar<typeof User>) {
const [name, age, isVerified] = args;
// do something
}
buildRoute("userId1", "companyId2"); // only accepts string parameters
otherFunction("John", 36, false); // accepts string, number and boolean parameters
原答案:
或者,如果您可以为变量定义数组类型,您可以像这样获得参数的确切数量及其类型:
type RouteParams = [
userId: string,
companyId: string,
]
function buildRoute(...routes: RouteParams): string {
const [userId, companyId] = routes;
// do something
}
buildRoute("user1", "company2")
最好用代码解释:
const ROUTE_PARAMS = {
userId: 'userId',
companyId: 'companyId',
};
// Is this somehow possible?
// `typeof` is obviously not the right tool here, just used as an example.
function buildRoute(typeof ROUTE_PARAMS): string;
// Result should be similar to:
function buildRoute2(userId: string, companyId: string): string;
// The function should be called like this:
buildRoute('some-user-id', 'some-company-id');
// I don't want the function to accept only 1 object like this:
buildRoute({ userId: 'some-user-id', companyId: 'some-company-id' });
想法是让 buildRoute
的路由参数以某种方式动态“绑定”到对象。
当“手动”定义函数参数时(如 buildRoute2
),我总是必须在更改 ROUTE_PARAMS
...
附加信息
我会尝试添加一些信息,因为我上面的问题似乎不够清楚:
- 我正在明确地寻找一种从 对象 中“输入”此函数的方法,如上所示 (
ROUTE_PARAMS
)。 - 我无法将其更改为其他结构(元组类型、某种数组...),因为这需要重构代码中与对象
ROUTE_PARAMS
一起使用的其他部分。 - 该函数应将每个对象 属性 作为单个输入参数(即函数 arity === 对象属性的数量)除外。
我不希望函数接受打包到 1 个对象中的所有属性(& 上面的示例)。
起初,我认为通过使用元组类型的展开运算符可以轻松实现您想要的结果。例如,
function f(...args: [string, string]) {}
与
相同(参数名称除外)function f(arg0: string, arg1: string) {}
所以我们可以尝试:
const ROUTE_PARAMS = {
userId: 'userId',
companyId: 'companyId',
};
function buildRoute(...args: typeof ROUTE_PARAMS[keyof typeof ROUTE_PARAMS][]): void {}
然而,typeof ROUTE_PARAMS[keyof typeof ROUTE_PARAMS][]
是一个数组,因此我们可以为生成的 buildRoute
函数提供任意数量的参数。它实际上与您编写 function buildRoute(...args: string[])
时相同。此外,当值不仅是 string
s,而且例如包含 number
时,推断类型将是 (string | number)[]
并且我们可以在以下位置提供 number
任意位置。
与上面 f
的不同之处在于,传播变量的类型是 tuple for f
但 array 对于 buildRoute
。所以我们需要从 ROUTE_PARAMS
的值中得到一个元组。但是,不幸的是,这不受支持,也不会得到支持,因为相应的提议被拒绝了:https://github.com/microsoft/TypeScript/issues/13298.
所以我现在认为您想要的可能无法通过 TypeScript 实现。
更新答案:
如
但是,只是为了扩展 Remirrors 答案以使语法更清晰一些,您可以创建一个使用泛型的全局类型。然后可以在您需要的所有地方重复使用,而无需重复重写长 keyof 代码:
// Re-useable type
export type TypeFromVar<T> = T[keyof T][];
const ROUTE_PARAMS = {
userId: 'userId',
companyId: 'companyId',
};
const User = {
name: 'Reece',
age: 25,
isVerified: true,
}
function buildRoute(...routes: TypeFromVar<typeof ROUTE_PARAMS>) {
const [userId, companyId] = args;
// do something
}
function otherFunction(...person: TypeFromVar<typeof User>) {
const [name, age, isVerified] = args;
// do something
}
buildRoute("userId1", "companyId2"); // only accepts string parameters
otherFunction("John", 36, false); // accepts string, number and boolean parameters
原答案:
或者,如果您可以为变量定义数组类型,您可以像这样获得参数的确切数量及其类型:
type RouteParams = [
userId: string,
companyId: string,
]
function buildRoute(...routes: RouteParams): string {
const [userId, companyId] = routes;
// do something
}
buildRoute("user1", "company2")