6

Edit Sorry my question was a bit unclear. I want to enforce that the getList Parameter is always required. So I don't have a default value for it. e.g I want the user always to supply a getlist

I'm trying to create a constuctor with some optional parameters and some required

export class PageConfig {
    constructor({
        isSliding = false,
    }: {
        isSliding?: boolean
        getList: (pagingInfo: PagingInfo) => Observable<any>
    } = {  }) { }
}

When I do this I'm getting an error

getList is missing in type '{}' but required in type ...

I would like to be able to use this in a class like so:

class UsersPage {

    config = new pageConfig({ this.getList })    

    getList(pagingInfo: PagingInfo) {
      // do work...
    }
}

Note: I've simplified the class for this example but I have a lot more properties, I'd like to leverage desturcturing so I don't have to configure the instantiation of my classes other than from the declaration

How can I enforce that getList must be passed during destructuring?

9
  • I think you’ll want to define an interface of arguments for your constructor. Commented Aug 23, 2019 at 23:37
  • config = new pageConfig({ ...this.getList }) Commented Aug 23, 2019 at 23:39
  • 1
    😕I'm confused. Where do you want to use destructuring? In the PageConfig constructor implementation signature? Or inside calls to the PageConfig constructor? If the former, it's going to be redundant like constructor({ isSliding = false, getList }: { isSliding?: boolean; getList: GetListFunc;}). If the latter, new PageConfig({this.getList}) isn't valid syntax; you might need to do new PageConfig(this) or new PageConfig({getList: this.getList}). But I really don't understand the intended use case enough to make these into answers. Commented Aug 24, 2019 at 0:28
  • 1
    @jcalz You cannot do destructuring in a call. Commented Aug 24, 2019 at 11:17
  • 2
    Why did you declare getList as a property of your parameter, but then did not use it in the destructuring? Commented Aug 24, 2019 at 11:19

3 Answers 3

5

You use a default value {} for the PageConfig constructor argument, but you marked getList as required in the type. If I understand you correctly, you want to have the constructor argument and getList always set, so change your code to:

export class PageConfig {
  constructor({
    getList,
    isSliding = false
  }: {
    getList: (pagingInfo: PagingInfo) => Observable<any>;
    isSliding?: boolean;
  }) {
    … // use getList and isSliding
  }
}

This syntax (destructuring with default values) can be a bit cumbersome sometimes. It gets clearer, when you extract the constructor argument type.

TypeScript docs example

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

1 Comment

thanks for answering my question, I've created another related one on how to expose the constructor arguments as public properties of the class, If you have time it might be an opportunity to get some easy points since you seem to be familiar with this field. The question is here
3

You want to remove the default, and also change the parameter order - required parameters always come before optional parameters:

constructor(getList: (pagingInfo: PagingInfo) => Observable<any>, isSliding?: boolean = false) {...}

6 Comments

I got the impression he does want the default value
required parameters always come before optional parameters are you sure about that? The question (and your answer) uses object destrucuring on the first argument of the constructor. Object keys are unordered. Required vs optional is irrelevant in this situation.
Fixed @JakeHolzinger and MinusFour.
This will work, but it changes the contract proposed in the question. However, it could be an acceptable alternative.
@JackBashford, I was attempting to do it this way first, but, Imagine you have another optional parameter after isSliding, how can you supply that parameter, with out supplying isSliding? e.g I have 10 optional parameters, Is there a way to call the constructor while leveraging only some of the defaults?
|
2

One option if it is the case that all constructor parameters are optional/have a default value would be simply to use a Partial config in the constructor and merge with defaults, e.g.

interface IPageConfigConstructor {
  isSliding: boolean;
  getList: (pagingInfo) => Observable<any>;
}
const DEFAULT_CONFIG:IPageConfigConstructor = {
  isSliding: true,
  getList: (pagingInfo) => null
}

class PageConfig {
  constructor(config: Partial<IPageConfigConstructor>) {
    const mergedConfig:IPageConfigConstructor = {...DEFAULT_CONFIG,...config}
  }
}

class UsersPage {
  config = new PageConfig({getList:(pagingInfo)=>this.getList(pagingInfo)});

  getList(pagingInfo) {
    // do work...
    return new Observable
  }
}

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.