Должен ли я использовать утверждение типа при создании массива | неопределенных объектов?

#typescript

Вопрос:

Каков наилучший маршрут для выполнения следующих действий в машинописном тексте:

У меня есть объект, который выглядит следующим образом:

 export interface TestConfig {
    configSql: MsSqlDatabaseConfig | undefined;
    userSql: MsSqlDatabaseConfig | undefined;
}
 

Позже я хочу создать массив из двух конфигураций в объекте, например

 let dbConfigs: MsSqlDatabaseConfig[] = [config.configSql, config.userSql];
 

Однако Машинопись сообщает об этом MsSqlDatabaseConfig | undefined is not assignable to type MsSqlDatabaseConfig , что имеет смысл.

Но если я ранее гарантировал в своем коде, что эти значения не являются неопределенными, каков наилучший способ разрешить компилятору использовать эти значения в моем массиве? Мне нужны | undefined асинхронные вызовы, которые извлекают данные, и я не могу использовать асинхронные методы в конструкторе класса, поэтому значения должны начинаться как неопределенные.

Приведение типов двух значений похоже на то, что я включаю типы в массив.

 let dbConfigs: MsSqlDatabaseConfig[] = [<MsSqlDatabaseConfig> config.configSql, <MsSqlDatabaseConfig> config.userSql];
 

Есть ли лучший способ?

Редактировать

Сначала вызывается метод resetDatabaseToKnownState (), который извлекает некоторые значения из моего файла env и анализирует их в допустимый объект. Значения configSql и userSql затем отображаются с этого момента и далее.

 public async resetDatabaseToKnownState(): Promise<void> {
        // Setup
        this.testConfig = await this.getSetupConfig();
    }

    private async getSetupConfig(){
        let configSql: MsSqlDatabaseConfig = JSON.parse(process.env.configDatabaseInfo!);
        let userSql: MsSqlDatabaseConfig = JSON.parse(process.env.userDatabaseInfo!);

        return {
            configSql: configSql,
            userSql: userSql
        }
    }
 

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

1. «Но если я ранее гарантировал в своем коде, что эти значения не являются неопределенными…» В обычном случае TypeScript может увидеть, что вы это сделали, сузить тип для вас и не вызывать ошибку. Можете ли вы показать нам, как вы это сделали? Возможно, мы сможем помочь вам понять, почему TypeScript не может его увидеть.

2. @Ти Джей Краудер, я обновил операцию. Я знаю об ! операторе, однако я стараюсь, чтобы мой код не был завален ими. Однако, похоже, я не могу иметь это в обоих направлениях

3. Исправление того, что вы описали, звучит так, как будто это потребует больших изменений, чем мы можем предложить здесь (например, найти способ не иметь одного и того же объекта: А) возможно, имеют неопределенные значения и Б) определенно не имеют неопределенных значений). Возможно, вместо того, чтобы иметь побочный эффект, resetDatabaseToKnownState можно было бы вернуть известную-не-будущую- undefined версию объекта? Что-то в этом роде. Возможно, это невозможно, и, если возможно, это может быть большим изменением, чем вы можете сделать прямо сейчас, но это именно то, что нужно. 🙂 Удачи!

Ответ №1:

Но если я гарантировал ранее в своем коде, что эти значения не являются неопределенными…

В обычном случае TypeScript может видеть, что вы это сделали, сузить тип для вас и не вызывать ошибку. Например:

 function example(x: {value: string | undefined}) {
    if (x.value) {
        console.log(x.value.toLocaleLowerCase()); // No error
    }
}
 

Таким образом, вы можете настроить свой код так, чтобы TypeScript мог видеть, что вы сузили тип.

В редкой ситуации, когда вам нужно выполнить утверждение, проще всего использовать ! постфиксный оператор машинописного текста «not null или undefined».:

 let dbConfigs: MsSqlDatabaseConfig[] = [config.configSql!, config.userSql!];
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^−−−−−−−−−−−−−−−−^
 

! это утверждение типа, поэтому, как и все утверждения типа, его лучше избегать, где это возможно. Иногда для этого требуются более значительные структурные изменения, чем в простом примере, показанном выше.