0

given following code:

class ConnectionOptions
{
    host: string = "localhost";
    port: number = 5672;
    username: string = "guest";
    password: string = "guest";
}

class ConnectorClass
{
    options: ConnectionOptions = new ConnectionOptions();

    SetOptions(options: ConnectionOptions)
    {
        console.log(options);
        this.options = options;
    }
}

// Adopt singleton pattern
var Connector = (function () {
    var instance : ConnectorClass;

    function createInstance() {
        return new ConnectorClass();
    }
 
    return {
        I: function () : ConnectorClass {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

// TestApp
Connector.I().SetOptions({ 'host': "192.168.17.5" });

In the last line there is following typescript error:

index.ts:50:26 - error TS2345: Argument of type '{ host: string; }' is not assignable to parameter of type 'ConnectionOptions'.
  Type '{ host: string; }' is missing the following properties from type 'ConnectionOptions': port, username, password

50 Connector.I().SetOptions({ 'host': "192.168.17.5" });

I understand why the error is thrown: TS is expecting 4 properties but I only want to set 1 of them, isnt this possible in Typescript?

1 Answer 1

1

For your code, an interface seems more suitable than a class. You have several classes implementing the interface if required. Then, if you want some of arguments to be optional, you may use the optional modifier (?):

interface ConnectionOptions {
    host?: string;
    port?: number;
    username?: string;
    password?: string;
}

const DefaultConnectionOptions: ConnectionOptions = {
  host: 'localhost',
  port: 5672,
  username: 'guest',
  password: 'guest',
}

Now your SetOptions method can look something like this:

    options: ConnectionOptions = DefaultConnectionOptions;

    SetOptions(options: ConnectionOptions) {
        console.log(options);
        this.options = { ...DefaultConnectionOptions, ...options };
    }

Your call Connector.I().SetOptions({ 'host': "192.168.17.5" }); should now work because no property is mandatory.


It may be that you want all connection options to be mandatory, but when calling SetOptions they are not mandatory. In that case do not use the optional modifier on the properties. Change your SetOptions signature to use Partial<T> instead:

    SetOptions(options: Partial<ConnectionOptions>) {
        console.log(options);
        this.options = { ...DefaultConnectionOptions, ...options };
    }

The above will still force this.options to have every single property, but the argument options does not have to provide all properties.

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

2 Comments

Thank you very much, it works fine! Can u maybe explain why a class is not the best option here? I came from C#, in where I would have done this 100% with a class.#
In typescript, a wide-spread pattern is to code for interfaces. Then have implementations for the interface as required. This makes the code - in general - more flexible because the focus is not in the implementation (there are articles on this pattern that can further explain). Also, the wide use of anonymous objects in javascript ({ host: 'localhost' }) can be more easily supported with interfaces (instead of having to do SetOptions(new ConnectionOptions(....)))

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.