有什么方法可以 "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...

的属性时使它们保持同步

附加信息

我会尝试添加一些信息,因为我上面的问题似乎不够清楚:

起初,我认为通过使用元组类型的展开运算符可以轻松实现您想要的结果。例如,

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[]) 时相同。此外,当值不仅是 strings,而且例如包含 number 时,推断类型将是 (string | number)[] 并且我们可以在以下位置提供 number 任意位置。

与上面 f 的不同之处在于,传播变量的类型是 tuple for farray 对于 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")