doplumi
doplumi

Reputation: 3118

Why am I unable to destructure an optional parameter, even after providing a valid default?

Is this just a lack of feature or a bug in my code?

The goal is to make users able to call my functions without providing the options, and still destructure the options in the signature.

// Typings
export interface MyFunctionOptions {
  optParam?: boolean;
}
export type MyFunction = (mandatoryParam: string, 
                          opts?: MyFunctionOptions) => void;

// Functions
const myFunction: MyFunction = (mandatoryParam, { 
                                  optParam,
                                } = { optParam: false }) => {
  // use `optParam` directly, instead of `opts.optParam`
  return;
}

Interactive REPL here (be sure to enable strictNullChecks in the REPL

Upvotes: 1

Views: 152

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249506

The syntax to specify default values for destructured parameters is {param = default}:

function foo({param = true}) {
    console.log(param) // param is boolean
}

foo({}) // the parameter is required
foo({ param: true}) 

To make the parameter itself optional we can specify a default of {} for the parameter as a whole:

function foo({param = true} = {}) {
    console.log(param) // param is boolean
}

foo() // the parameter is optional

If we apply this logic to your sample we get :

const myFunction = (mandatoryParam: string, { optParam = false } = {}) => {
    optParam
    return;
}
myFunction("") // not required
myFunction("", {}) // optParam is optional
myFunction("", { optParam: true }) // optParam can be set 

The problem appears when we try to specify the type of the function explicitly, then the second parameter is inferred to be MyFunctionOptions | undefined which is not indexable in any way. The simple solution to this unfortunate inference is to specify the type of the de-structured parameter explicitly:

const myFunction: MyFunction = (mandatoryParam: string, { optParam = false } : MyFunctionOptions = {}) => {
    optParam
    return;
}
myFunction("")
myFunction("", {})
myFunction("", { optParam: true })

Playground link

Upvotes: 1

Related Questions