3

In Typescript, when assigning a default value to a parameter of type string, the empty string counts as something and the default value is not used.

This makes sense, but in some cases, I'd like to change that:

function greet (name?: string = 'visitor') {
  console.log(`Hello ${name}`)
}
greet('Gromit') // logs "Hello Gromit"
greet() // logs "Hello visitor"
greet('') // logs "Hello " <--- How can I get the default value in this case too?

Does Typescript perhaps have a feature, which I am not finding, to help define when I want the default value to apply?

I have been using what I consider to be a workaround, for now:

const defaultName = 'visitor'
function greet (name?: string = defaultName) {
  const finalName = name || defaultName
  console.log(`Hello ${finalName}`)
}

But I would rather use something cleaner and more idiomatic to Typescript and I would be surprised if a better pattern doesn't exist.

To be clear, I would have expected to find a way to do this within that part of the code responsible for defining the function parameters:

function greet (/* here */) {}

The proposed solutions introduce code outside of this section the same as I do in my workaround.

Thanks for any pointers!

3 Answers 3

10

There's no way to define this condition inside the function arguments. The cleanest way I can think of is simply to check and replace the value inside the function body:

function greet(name?: string) {
  name = name || 'visitor'
  // other code
}
Sign up to request clarification or add additional context in comments.

4 Comments

This is pretty much the same thing as my workaround, but here we lose the default value in the function parameter itself, which harms the IDE integration that Typescript is usually so good at as well as the self-documenting nature of the code…
@Shawn What IDE integration are you talking about? I can't see any difference from the caller's side between the function with a default parameter vs a function with an optional parameter; both show as (essentially) function greet(name?: string): void.
Imagine generating docs from this, how could the doc generator know about the default value in the case of greet2?
You can also use the shorthand assignment: name ||= 'visitor'
2

A better pattern doesn't exist, because it would conflict with the perfectly reasonable behavior that "" overrides the default non-empty value.

You have two different ways of specifying default-like behavior, one of which is an absent value, and one of which provides a value if passed an empty/falsy value. These might happen to result in the same value, but there isn't a more-concise pattern to represent this in the function signature or implementation.

The only modification I would make to MaartenDev and Vojtěch Strnad's answers would be to document the default value in JSDoc, which might accomplish your goal of IDE integration. (Unfortunately, even then JSDoc's optional/default value support [name="visitor"] isn't visible in TypeScript Playground or VSCode.)

/**
 * Greets a person.
 *
 * @param [name] Name to greet. "visitor" if falsy or absent.
 */
function greet(name?: string) {
  name = name || 'visitor'
  // other code
}

Playground Link

3 Comments

Also, we get this default value defined twice here: once in the comment and once in the body of the function, making it possible for them to fall out of sync… I don't usually need this because I can usually just avoid calling the function with an empty string, but I'm in a situation with my CMS where it's not differentiating between an empty string and a value not provided by the user… Real pain.
@Shawn I understand the ways in which it's not ideal compared to what you want, but I hope you understand the reasons I think that what you want doesn't exist as such. I think that between your question, my answer, and Vojtěch Strnad's answer, that might be the best you'll get.
Yeah, I'm starting to get that impression as well. I do understand, you know. I'm not advocating to change the defaults, I'm just surprised there isn't an extra feature for what seems to be a common issue here… I'm not looking into the darkest corners of the language to find imperfections here, I'm just addressing an issue I'm having on a day-to-day basis and I'm very surprised that no one is coming up with a solution. I was expecting advice about creating a NonEmptyString type which could achieve this or something, but my expectations for Typescript may simply be wrong, indeed.
2

Observation : As you are initializing a default value to name parameter, it makes that parameter optional. Hence, no need to add Question mark (?) explicitly as it will through a below compilation error.

Parameter cannot have question mark and initializer.

Regarding the issue you are facing, You can get rid from that by using Conditional (ternary) operator

function greet (name:string = 'visitor') {
    console.log(`Hello ${name}`)
}
 
greet('' ? '' : undefined) // Hello visitor

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.