508

Given the following signature:

export interface INotificationService { error(message: string, title?: string, autoHideAfter?: number); } 

How can I call the function error() not specifying the title parameter, but setting autoHideAfter to say 1000?

12 Answers 12

547

As specified in the documentation, use undefined:

export interface INotificationService { error(message: string, title?: string, autoHideAfter? : number); } class X { error(message: string, title?: string, autoHideAfter?: number) { console.log(message, title, autoHideAfter); } } new X().error("hi there", undefined, 1000); 

Playground link.

Sign up to request clarification or add additional context in comments.

4 Comments

@BBi7 I think you misunderstood the documentation. The ? is added in the function definition, but the question is about actually calling the function.
Hi @Thomas I totally understand the documentation and know you must add the ? after the parameter in the function definition. But, related to calling a function with optional parameter(s) I'd assume passing undefined if not applicable. I generally I try to find ways to make optional parameter(s) as the end parameter(s) so I can just not pass vs. undefined. But obviously if you have many then you'd need to pass undefined or anything non-truthy. I'm not sure what I was referring to back when I originally posted. Meaning I don't know if it was edited but what I see now fine correct.
@BBi7 There were no recent edits. Okay, never mind then :) (Note that you actually must pass undefined to get the same behaviour as leaving out the argument entirely. Just "anything non-truthy" will not work, because TypeScript actually compares to void 0 which is a safer way of writing undefined.)
@Thomas actually this was the crucial information: if you want the default value to apply to say the first argument and then set the second one, you must specify undefined as the first "value".
120

Unfortunately there is nothing like this in TypeScript (more details here: https://github.com/Microsoft/TypeScript/issues/467)

But to get around this you can change your params to be an interface:

export interface IErrorParams { message: string; title?: string; autoHideAfter?: number; } export interface INotificationService { error(params: IErrorParams); } //then to call it: error({message: 'msg', autoHideAfter: 42}); 

1 Comment

Could you please tell, can i call the error method as this, error({message : 'test'}), I think, we can't, so error({message : 'test', autoHideAFter: undefined}), but what i'm expecting is error(message), If i didn't pass other paramers, it shold take the values from default parameters.
69

Another approach is:

error(message: string, options?: {title?: string, autoHideAfter?: number}); 

So when you want to omit the title parameter, just send the data like that:

error('the message', { autoHideAfter: 1 }) 

I'd rather this options because allows me to add more parameter without having to send the others.

You can also use Partial<T> type in method's signature but it this case you have to create an interface for your options:

interface IMyOptions { title: string; autoHideAfter: number; } 

And then the method's signature can look like:

error(message: string, options?: Partial<IMyOptions>); 

Usage is the same as above.

Type Partial<T> should already be declared in global typings as following:

type Partial<T> = { [P in keyof T]?: T[P]; }; 

2 Comments

How would you also pass a default value to title?
@DanDascalescu ..., options?: {title?: string} = {title: "my default"}, ...
39

you can use optional variable by ? or if you have multiple optional variable by ..., example:

function details(name: string, country="CA", address?: string, ...hobbies: string) { // ... } 

In the above:

  • name is required
  • country is required and has a default value
  • address is optional
  • hobbies is an array of optional params

3 Comments

Shouldn't hobbies be typed as an array ?
There's a useful info in this answer, but it doesn't answer the question. The question is, as I see it, how one can bypass/skip several optional parameters and set only specific ones.
country isn't required, it's an optional param having a default value of 'CA' instead of undefined. if it's required then what's the point of providing default value?
15

This is almost the same as @Brocco 's answer, but with a slight twist: only pass optional parameters in an object. (And also make params object optional).

It ends up being kind of like Python's **kwargs, but not exactly.

export interface IErrorParams { title?: string; autoHideAfter?: number; } export interface INotificationService { // make params optional so you don't have to pass in an empty object // in the case that you don't want any extra params error(message: string, params?: IErrorParams); } // all of these will work as expected error('A message with some params but not others:', {autoHideAfter: 42}); error('Another message with some params but not others:', {title: 'StackOverflow'}); error('A message with all params:', {title: 'StackOverflow', autoHideAfter: 42}); error('A message with all params, in a different order:', {autoHideAfter: 42, title: 'StackOverflow'}); error('A message with no params at all:'); 

Comments

9

You can specify multiple method signatures on the interface then have multiple method overloads on the class method:

interface INotificationService { error(message: string, title?: string, autoHideAfter?: number); error(message: string, autoHideAfter: number); } class MyNotificationService implements INotificationService { error(message: string, title?: string, autoHideAfter?: number); error(message: string, autoHideAfter?: number); error(message: string, param1?: (string|number), param2?: number) { var autoHideAfter: number, title: string; // example of mapping the parameters if (param2 != null) { autoHideAfter = param2; title = <string> param1; } else if (param1 != null) { if (typeof param1 === "string") { title = param1; } else { autoHideAfter = param1; } } // use message, autoHideAfter, and title here } } 

Now all these will work:

var service: INotificationService = new MyNotificationService(); service.error("My message"); service.error("My message", 1000); service.error("My message", "My title"); service.error("My message", "My title", 1000); 

...and the error method of INotificationService will have the following options:

Overload intellisense

Playground

3 Comments

Just a note that I would recommend against this and instead pass in an object and put these parameters as properties on that object... it's a lot less work and the code will be more readable.
This just isn't a good idea. What if I have three string parameters but want to omit only one of the parameters? This won't work as all three overrides would have the same signature
The params assignment looks quite fragile and hard to maintain. Besides, if yet another param was needed in the future, it would entail even more juggling.
3

In TS you could also make your parameters into an Object and make the value of the object optional, that way you don't have to define every parameters, just the one you want to use.

public functionBeingCalled(obj: {status?: number, error?: string, message?: string}) { if(obj.message) { console.log(obj.message) } } this.functionBeingCalled({message: 'Error Detected'})

Comments

2

You can create a helper method that accept a one object parameter base on error arguments

 error(message: string, title?: string, autoHideAfter?: number){} getError(args: { message: string, title?: string, autoHideAfter?: number }) { return error(args.message, args.title, args.autoHideAfter); } 

Comments

-1

In such cases you can use "undefined" value for those optional params which you do not want to overwrite

export interface INotificationService { error(message: string, title?: string, autoHideAfter?: number); } 

You can call error method like

error("it works", undefined, 20); 

Be careful null doesn't work here.

1 Comment

This method, passing undefined, is the same as the accepted answer. Why give a duplicate answer?
-1

https://www.typescriptlang.org/docs/handbook/functions.html

In JavaScript, every parameter is optional, and users may leave them off as they see fit. When they do, their value is undefined. We can get this functionality in TypeScript by adding a ? to the end of parameters we want to be optional. For example, let’s say we want the last name parameter from above to be optional:

function buildName(firstName: string, lastName?: string) { if (lastName) return firstName + " " + lastName; else return firstName; } let result1 = buildName("Bob"); // works correctly now let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters Expected 1-2 arguments, but got 3. let result3 = buildName("Bob", "Adams"); // ah, just right 

1 Comment

Same comment as for the linked answer: you didn't answer the question, or you didn't read it.
-2

You can do this without an interface.

class myClass{ public error(message: string, title?: string, autoHideAfter? : number){ //.... } } 

use the ? operator as an optional parameter.

2 Comments

but this doesn't allow you any way to specify message and autoHideAfter
you don't answer the question or you didn't read it. He wants to know how to call a method with multiple optional parameters, without having to specify the first optional if he only want to enter the second one.
-3

You could try to set title to null.

This worked for me.

error('This is the ',null,1000) 

2 Comments

This woulndt work since if the function parameter has a default value when you sent null to that function parameter will not set to it's default value
you may remove your answer since it's totaly wrong

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.