Почему TypeScript объявляет мой параметр как undefined?

Вопрос или проблема

В следующей функции я пытаюсь вызвать метод getSelectProduct сервиса ProductServices.

  private getSelectedProduct = () => {
    const productId = this.activatedRoute.snapshot.paramMap.get('productId');
    console.log('selectedProduct', productId)
    this.productService.getSelectedProduct(productId).subscribe(product => {
      this.selectedProduct = product;
    })
  }

TypeScript показывает мне красную волну под productId в этом выражении: getSelectedProduct(productId). Сообщение об ошибке:

Аргумент типа ‘string | null’ не может быть присвоен параметру типа ‘string’.
Тип ‘null’ не может быть присвоен типу ‘string’.ts(2345)
const productId: string | null

Вот объявление selectedProduct: public selectedProduct?:ProductModel;

Это метод getSelectedProduct:

public getSelectedProduct = (productId:string) => {
    const product = this.productSignal().products.find(product => product._id === productId)
    return of(product)
  }

Основываясь на совете Гая Инкогнито: учитывать случай, когда productId равен null;

private getSelectedProduct = () => {
    const productId = this.activatedRoute.snapshot.paramMap.get('productId');
    console.log('selectedProduct', productId)
    if(productId !== null) {
      this.productService.getSelectedProduct(productId).subscribe(product => {
        this.selectedProduct = product;
        console.log('selectedProduct', this.selectedProduct)
      })
    }    
}

Ответ или решение

Вопрос о том, почему TypeScript рассматривает ваш параметр как undefined, является распространенной проблемой, с которой сталкиваются разработчики при работе с параметрами, полученными из URL, особенно в контексте фреймворков, таких как Angular. Давайте подробно рассмотрим ваш код, причины возникновения данной проблемы и возможные решения.

Проблема

Ваш метод getSelectedProduct вызывает метод getSelectedProduct из сервиса productService и передает полученное значение productId, которое вы получаете из activatedRoute.snapshot.paramMap.get('productId'). Однако TypeScript сообщает вам, что аргумент типа 'string | null' не может быть присвоен параметру типа 'string'. Это происходит потому, что метод get может вернуть либо строку (в случае успешного извлечения параметра), либо null (если параметр не найден).

Ошибка Типизации

Ваша ошибка:

Argument of type 'string | null' is not assignable to parameter of type 'string'.
Type 'null' is not assignable to type 'string'.ts(2345)

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

Решение

Чтобы избежать данной ошибки, вам следует учитывать возможность того, что productId может быть null. Вы правильно сделали, добавив проверку на null в обновленном коде:

private getSelectedProduct = () => {
    const productId = this.activatedRoute.snapshot.paramMap.get('productId');
    console.log('selectedProduct', productId)
    if (productId !== null) {
        this.productService.getSelectedProduct(productId).subscribe(product => {
            this.selectedProduct = product;
            console.log('selectedProduct', this.selectedProduct)
        })
    }    
}

Альтернативные Подходы

  1. Использование утверждения типов (Type Assertion):
    Если вы уверены, что productId никогда не будет null в контексте вашего приложения, вы можете использовать утверждение типа (type assertion):

    this.productService.getSelectedProduct(productId as string)

    Однако используйте этот подход с осторожностью, так как он может привести к ошибкам, если productId все же окажется null.

  2. Значение по умолчанию:
    Вы можете использовать значение по умолчанию. Например, если productId равен null, можно использовать пустую строку или другое значение:

    const productId = this.activatedRoute.snapshot.paramMap.get('productId') || '';

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

Заключение

Для минимизации проблем с типизацией важно всегда учитывать возможность возникновения null, особенно при работе с данными из внешних источников, таких как URL-параметры. Ваше решение с проверкой if (productId !== null) является надёжным способом избежать ошибки. Оставайтесь внимательными к типам данных и их изменяющейся природе: это значительно улучшит устойчивость и надёжность вашего кода.

Оцените материал
Добавить комментарий

Капча загружается...