Необязательный параметр класса в typescript

#typescript

#typescript

Вопрос:

приведен следующий код:

 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" });
 

В последней строке есть следующая ошибка машинописного текста:

 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" });
 

Я понимаю, почему выдается ошибка: TS ожидает 4 свойства, но я хочу установить только 1 из них, разве это невозможно в Typescript?

Ответ №1:

Для вашего кода интерфейс кажется более подходящим, чем класс. При необходимости у вас есть несколько классов, реализующих интерфейс. Затем, если вы хотите, чтобы некоторые из аргументов были необязательными, вы можете использовать необязательный модификатор ( ? ):

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

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

Теперь ваш SetOptions метод может выглядеть примерно так:

     options: ConnectionOptions = DefaultConnectionOptions;

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

Теперь ваш вызов Connector.I().SetOptions({ 'host': "192.168.17.5" }); должен работать, потому что никакое свойство не является обязательным.


Возможно, вы хотите, чтобы все параметры подключения были обязательными, но при вызове SetOptions они не являются обязательными. В этом случае не используйте необязательный модификатор для свойств. Измените свою SetOptions подпись, чтобы использовать Partial<T> вместо:

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

Приведенное выше по-прежнему будет вынуждать this.options иметь каждое отдельное свойство, но аргумент options не обязательно должен предоставлять все свойства.

Комментарии:

1. Большое вам спасибо, все работает отлично! Может быть, вы можете объяснить, почему класс здесь не лучший вариант? Я пришел из C #, где я бы сделал это на 100% с классом.#

2. В typescript широко распространенным шаблоном является кодирование интерфейсов. Затем создайте необходимые реализации для интерфейса. Это делает код — в целом — более гибким, поскольку основное внимание уделяется не реализации (есть статьи по этому шаблону, которые могут дополнительно объяснить). Кроме того, широкое использование анонимных объектов в javascript ( { host: 'localhost' } ) может быть легче поддержано с помощью интерфейсов (вместо необходимости делать SetOptions(new ConnectionOptions(....)) )