Use:

interface InputObj {
    arg1: number;
    arg2: number;
    arg3: number;
}

interface ExampleProps {
    sum: (input: InputObj) => number
}

Or inline:

interface ExampleProps {
  sum: (
    input: {
      arg1: number;
      arg2: number;
      arg3: number;
    }
  ) => number;
}

But depending on your use case you may not need to define ExampleProps. Here is your sum function without the arbitrary input object name:

const sum = ({
  arg1,
  arg2,
  arg3
}: {
  arg1: number;
  arg2: number;
  arg3: number;
}) => arg1 + arg2 + arg3;
Answer from automasean on Stack Overflow
Top answer
1 of 4
9

Use:

interface InputObj {
    arg1: number;
    arg2: number;
    arg3: number;
}

interface ExampleProps {
    sum: (input: InputObj) => number
}

Or inline:

interface ExampleProps {
  sum: (
    input: {
      arg1: number;
      arg2: number;
      arg3: number;
    }
  ) => number;
}

But depending on your use case you may not need to define ExampleProps. Here is your sum function without the arbitrary input object name:

const sum = ({
  arg1,
  arg2,
  arg3
}: {
  arg1: number;
  arg2: number;
  arg3: number;
}) => arg1 + arg2 + arg3;
2 of 4
4

Here is a fully annotated example as function expression:

const sum: ({ 
  arg1, 
  arg2,
  arg3 
}: {
  arg1: number;
  arg2: number;
  arg3: number;
}) => number = ({ arg1, arg2, arg3 }) => arg1 + arg2 + arg3;

Here is another and better alternative for arrow functions. Only arguments are annotated and compiler can infer return type correctly. Function has less clutter and works just as before.

const sum = ({ 
  arg1,
  arg2,
  arg3
}: {
  arg1: number;
  arg2: number;
  arg3: number;
}) => arg1 + arg2 + arg3;

If you are going to annotate your function in a seperate file:

interface Args {
  arg1: number;
  arg2: number;
  arg3: number;
}

type Sum = (input: Args) => number;
const sum: Sum = ({ arg1, arg2, arg3 }) => arg1 + arg2 + arg3;

You can use any as argument type if argument types are not known. Return type will be inferred as any:

const sum = ({ 
  arg1,
  arg2,
  arg3
}: any) => arg1 + arg2 + arg3;

So this one is equivalent to previous example:

const sum: ({ arg1, arg2, arg3 }: any) => any

This may not make that much sense for arrow functions but you can set types for known arguments and use key-value pairs for annotating addititional argumens:

const sum = ({ 
  arg1,
  arg2,
  arg3
}: {
  arg1: number;
  arg2: number;
  arg3: number;
  [key: string]: number;
}) => arg1 + arg2 + arg3;

You can also use generics:

interface Args {
  arg1: number;
  arg2: number;
  arg3: number;
}

const sum = <T extends Args>({ 
  arg1,
  arg2,
  arg3
}: T) => arg1 + arg2 + arg3;

Here is same examples, sum as function statement.

function sum({
  arg1,
  arg2,
  arg3
}: {
  arg1: number;
  arg2: number;
  arg3: number;
}): number {
  return arg1 + arg2 + arg3;
}

If you have complicated implementation detail in your function's body, function statement can be better choice for its ergonomics. Plus generics looks less clumsy on function statements.

🌐
TypeScript
typescriptlang.org › docs › handbook › 2 › functions.html
TypeScript: Documentation - More on Functions
In TypeScript, the type annotation on these parameters is implicitly any[] instead of any, and any type annotation given must be of the form Array<T> or T[], or a tuple type (which we’ll learn about later). Conversely, we can provide a variable number of arguments from an iterable object (for example, an array) using the spread syntax.
Discussions

What are your rules-of-thumb for having a single object as the function arg, versus having many args?
For me this is roughlt the heuristic: - Multiple arguments: Only in very simple use cases. up to 2 inputs. inputs are distinct. - Hybrid: When there is one distinct argument and a config object - Object argument: All other cases :) More on reddit.com
🌐 r/typescript
15
11
July 15, 2023
Multiple Params vs "Object" Function Parameter?
Objects are also useful when you have multiple parameters of the same type. If you have a function that accepts two string args, TS won’t protect you against the caller passing them in the wrong order. You can use an object param so the args are keyed, which helps to protect against that. More on reddit.com
🌐 r/typescript
10
13
September 29, 2023
Typescript Function/Object parameters - javascript
Since there is no sortQuery object but instead a callback function. This is not giving me any type of error and means that typescript is allowing the callback as the object type. More on stackoverflow.com
🌐 stackoverflow.com
Typeof arguments object in TypeScript
function foo(){ // literally pass the arguments object into the pragmatik.parse method // the purpose of pragmatik.parse is to handle more complex variadic functions const [a,b,c,d,e] = pragmatik.parse(arguments); // now we have the correct arguments in the expected location, using array destructuring } ... so my question is: does TypeScript ... More on stackoverflow.com
🌐 stackoverflow.com
January 5, 2019
🌐
GitHub
github.com › microsoft › TypeScript › issues › 29055
Type JS's `arguments` object based on function parameters · Issue #29055 · microsoft/TypeScript
December 16, 2018 - Within a function x, the type of the arguments object should be Parameters<typeof x> & IArguments, with undefined removed from the type of any entries in Parameters<typeof x> if that parameter has a default value.
Author   microsoft
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Functions › arguments
The arguments object - JavaScript - MDN Web Docs - Mozilla
arguments is an array-like object accessible inside functions that contains the values of the arguments passed to that function.
🌐
Reddit
reddit.com › r/typescript › what are your rules-of-thumb for having a single object as the function arg, versus having many args?
r/typescript on Reddit: What are your rules-of-thumb for having a single object as the function arg, versus having many args?
July 15, 2023 -

I'm realising that writing a function with many arguments can lead to difficulties. For example, if you have function foo (a: string, b:string, c:string, ... z: string ) {..} you have an awful lot of code to precisely update when you want to remove the argument c from all calls of foo.

What are the pros and cons of passing many args, versus a single arg object with an associated interface, versus a hybrid approach of primitive args and object args?

Is there an article discussing this?

🌐
Damir's Corner
damirscorner.com › blog › posts › 20180216-VariableNumberOfArgumentsInTypescript.html
Variable Number of Arguments in TypeScript | Damir's Corner
February 16, 2018 - In TypeScript and ECMAScript 6 rest parameters and spread syntax provide a more convenient alternative that also works with arrow functions. There is an arguments object available in every JavaScript function as a local variable.
🌐
Webdevtutor
webdevtutor.net › blog › typescript-function-arguments-object
Understanding TypeScript Function Arguments Object
In conclusion, the arguments object in TypeScript provides a way to access all arguments passed to a function dynamically. However, it is advisable to use rest parameters for better type checking and code clarity.
Find elsewhere
🌐
LogRocket
blog.logrocket.com › home › how to pass a typescript function as a parameter
How to pass a TypeScript function as a parameter - LogRocket Blog
May 15, 2025 - In JavaScript and TypeScript, understanding the concepts of pass-by-value and pass-by-reference is crucial for working with functions and manipulating data. Primitive types (such as Boolean, null, undefined, String, and Number) are treated as pass-by-value, while objects (including arrays and functions) are handled as pass-by-reference. When an argument is passed to the function, pass-by-value means a copy of the variable is created, and any modifications made within the function do not affect the original variable.
🌐
Medium
fab1o.medium.com › named-parameters-in-typescript-288d90f35639
Named Parameters in TypeScript - Fabio Costa
January 30, 2024 - It’s very similar to a native named arguments. We do not create a type or interface for the object because it’s not a significant interface or type, it’s just named arguments.
Top answer
1 of 2
5

With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:

let v = {
  find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
  }
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })

A default parameter value can then be set like this:

sortQuery: Exclude<T, Function> = <any>{}

As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:

The errors that then display are as follows:

  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]
  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]
2 of 2
5

Objects and functions are fundamentally the same thing, but typings help us disambiguate between their functionality.

Consider this:

const foo1: { (): string } = () => "";

The variable foo has a type of object, but that object is callable ... it's a function, and it can indeed be called, but you can't go setting a property called bar on it.

foo1(); // This works
foo1.bar = 5; // This, not so much.

Also consider this:

const foo2: { bar?: number; } = {};

The variable foo has a property called bar on it. That property can be set, but the object can't be called, as it's not typed as callable.

foo2.bar = 5; // This works
foo2(); // This, not so much.

So, lets have a look at your original typing:

sortQuery = {}

sortQuery is an object, but that's all that we know about it. It doesn't have any properties, it's not callable, it's just an object.

We've already seen that a function is an object, so you can assign a function to it just fine. But, you won't be able to call it, as it's not defined as callable.

const sortQuery: {} = () => ""; // This works.
sortQuery(); // This, not so much.
sortQuery.bar = 5; // Nor this.

If you have full control of the source code, then one way to solve this is to move from multiple parameters, to a single parameter with named properties:

const foo = (params: { collection: string, query: object, sortQuery: {}, cb?: Function }) => { };

foo({ collection: "", query: {}, sortQuery: {} }); // Fine
foo({ collection: "", query: {}, sortQuery: {}, cb: () => { } }); // Fine
foo({ collection: "", query: {}, cb: () => { } }); // Not Fine

This removes any ambiguity by requiring names, rather than relying on position in the function call.

🌐
TypeScript
typescriptlang.org › docs › handbook › 2 › objects.html
TypeScript: Documentation - Object Types
You might read this as “A Box of Type is something whose contents have type Type”. Later on, when we refer to Box, we have to give a type argument in place of Type. ... Think of Box as a template for a real type, where Type is a placeholder that will get replaced with some other type. When TypeScript sees Box<string>, it will replace every instance of Type in Box<Type> with string, and end up working with something like { contents: string }. In other words, Box<string> and our earlier StringBox work identically.
🌐
Marius Schulz
mariusschulz.com › blog › typing-destructured-object-parameters-in-typescript
Typing Destructured Object Parameters in TypeScript — Marius Schulz
July 23, 2019 - In TypeScript, you can add a type annotation to each formal parameter of a function using a colon and the desired type, like this: function greet(name: string) { return `Hello ${name}!`; } That way, your code doesn't compile when you attempt ...
🌐
xjavascript
xjavascript.com › blog › typescript-arguments
Mastering TypeScript Arguments: A Comprehensive Guide — xjavascript.com
Try to keep the types as simple as possible. For example, instead of using a deeply nested object type as an argument, break it down into smaller, more manageable types. Use JSDoc or TypeScript's built-in type annotations to document the purpose and type of each argument.
Top answer
1 of 2
2

As already noted in the comments, arrow functions don't have the reserved arguments variable.

But you can still have type safety, a single named argument and default values if you just split up these requirements into different statements. That will also make the code much easier to read and understand:

interface Options {
    query: string | null;
}

const defaultOptions: Options = {
    query: null,
}

const doThing = async (options: Partial<Options>) => {
    const completeOptions: Options = Object.assign({}, defaultOptions, options);
};

Additionally the Options interface actually specifies the strucure that you need inside the function body this way.

Also you can now pass a partial set of options without having to specify all properties literally twice inline, where the value level of the signature -- { query = null } -- specified the default values before, and the type level -- { query?: string; } -- specified both the types and the fact that option keys are optional. The optional part is now done with the Partial type instead.

2 of 2
0

I think what you are looking for can be achieved by the using overloads of the function. This will allow:

  1. To have a function with a single parameter.
  2. Inform the different types to the type system.
  3. Change the function behavior depending on the type you received. (This violate the OOP principle of Single responsibility, but let's go back to your question...)

So your function overloads would look something like this:

function doThingFunc(arg: { query: string, somthingElse?: string }): void;
function doThingFunc(arg: string): void
function doThingFunc(arg: any): void {
  if (typeof arg === 'object') {
    console.log(arg.query);
  }
  if (typeof arg === 'string') {
    console.log(arg);
  }
}
const doThing = doThingFunc;


doThing('some query');
doThing({ query: 'some query', somthingElse: 'something else' });

Of course, with this implementation you lose the this binding when used inside an object that arrow functions provide out of the box. More details here: https://www.typescriptlang.org/docs/handbook/functions.html