0

I am trying to write all optional named parameters for a TypeScript function.

But I am having a lot of trouble assigning a type to the parameters, as can be illustrated by this example:

type Params = {
    foo: {
        bar: string,
        baz?: string
    }[]
}

function testFunction({foo= [{bar: "hi", baz: "there"}, {bar: "hello"}]}={}: Params) { // This fails, I don't know how to type it here
    console.log(foo)
}

testFunction()

What's the correct way to use named optional parameters in TypeScript while also being able to type the optional parameter object?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Molten Ice
  • 2,715
  • 1
  • 27
  • 37
  • For one thing it's always `name: type = value`, so `testFunction({...}: Params = {})`. – jonrsharpe Aug 26 '22 at 07:37
  • @jonrsharpe, that gives me this error: `Property 'foo' is missing in type '{}' but required in type 'Params'`. But I think you're getting close to how to solve it. Basically `foo` should always exist because the calling function either doesn't specify any parameter or if it does, it specifies foo. Do you know how I can achieve this? – Molten Ice Aug 26 '22 at 07:48

3 Answers3

2

there's a typo in your code

function testFunction({foo= [{bar: "hi", baz: "there"}, {bar: "hello"}]}={}: Params) {
    console.log(foo)
}

to declare a type you use :, not = . To assign a default value, you need to wrap your argument this way

interface Params {
    foo?: {
        bar: string,
        baz?: string
    }[]
}

function testFunction(arg: Params = {foo: [{bar: "hi", baz: "there"}, {bar: "hello"}]}) { 
    console.log(arg.foo)
}

testFunction() // <-- No error.

Playground link

soffyo
  • 545
  • 5
  • 15
1

If I understand your question correctly, you want the whole parameter to be optional. In that case, you have to write it like this:

function testFunction(params: Params = {foo: [{bar: "hi", baz: "there"}, {bar: "hello"}]}) {
    console.log(params.foo)
}

where {foo: [{bar: "hi", baz: "there"}, {bar: "hello"}]} is default value and you can call that function without parameter.

If you meant your question differently, please give us more details.

Jax-p
  • 7,225
  • 4
  • 28
  • 58
1

There is no such thing as "named parameters" in TypeScript or JavaScript. What you have is an optional parameter which is an object. And the syntax is the same as always: name: Type = defaultValue. The name can immediately be unpacked as {foo}; the Type is Params and the defaultValue is the default value of the entire object. So this is the correct syntax:

function testFunction({foo}: Params = {foo: [{bar: "hi", baz: "there"}, {bar: "hello"}]}) {
    console.log(foo)
}

But the default value won't help you here, because you said you wanted to emulate all optional named parameters. If you pass an object, the default value is entirely ignored, so the above is an all-or-nothing approach.

Instead, you'll have to make the default of each field in the object be undefined:

type Params = {
    foo?: {
        bar: string,
        baz?: string
    }[],
    qux?: number,
}

Then assign the default inside the function:

function testFunction({foo, qux}: Params = {}) {
    // Assign default values if a parameter is undefined
    foo = foo !== undefined ? foo : [{bar: "hi", baz: "there"}, {bar: "hello"}]
    qux = qux !== undefined ? qux : 42
}

You can still set {} as the default if the argument is entirely omitted, which will then do the same as omitting all object keys.

See e.g. this question for some more examples.

Thomas
  • 174,939
  • 50
  • 355
  • 478