проверка типа объединения числа и перечисления в машинописном тексте

#typescript

Вопрос:

Я создаю пакет npm SSML builder, используя Typescript.

У меня есть функция в typescript, например, приведенная ниже, которая преобразует объект просодии в тег SSML.

 prosody(attributes: ProsodyAttributes, word: string){

        const {rate, volume, pitch} = attributes;

        let tag = `<prosody `;

        if(rate){

            tag  = `rate="${rate}"`

        }

        if(pitch){

            tag  = `pitch="${pitch}"`

        }

        if(volume){

            tag  = `volume="${volume}"`

        }

        tag  = `>${this._escape(word)}</prosody>`;

        this._elements.push(tag);

        return this;

    }
 

Ниже приведены типы. Скорость, высота и громкость могут быть либо числами, либо определенным значением. Я создал перечисление для каждого из них. Я использую тип объединения для обслуживания как чисел, так и фиксированных значений.

 enum Rate{
    xslow = "x-slow",
    slow = "slow",
    medium = "medium",
    fast = "fast",
    xfast = "x-fast"
}

enum Pitch{
    xlow = "x-low",
    low = "low",
    medium = "medium",
    high = "high",
    xhigh = "x-high"
}

export enum Volume{
    silent = "silent",
    xsoft = "x-soft",
    soft = "soft",
    medium = "medium",
    loud = "loud",
    xloud = "x-loud"
}

interface ProsodyAttributes {
    rate?: Rate | number,
    pitch?: Pitch | number,
    volume?: Volume | number
}
 

как правильно проверить входные параметры функции?

Я попробовал что-то вроде кода ниже:

 if (typeof rate === "number"){

  if(rate < 20 || rate > 200){

    throw("attributes.rate is out of range")

  }

} else {

  if(!Object.values(Rate).includes(rate)){

    throw("attributes.rate is invalid");

  }

}
 

У меня есть следующие вопросы:

  1. Является ли это правильным подходом?
  2. Должен ли я использовать перечисления в первую очередь? Это перебор?

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

введите описание изображения здесь

Мой подход к разработке функции просодии вызывает несовместимость типов. Как мне с этим справиться?

Ответ №1:

Перечисления генерируются компилятором typescript. Это означает, что они существуют во время выполнения. Поэтому либо из javascript, либо из машинописного текста вы должны сделать:

 prosody({ volume: Volume.loud })
 

Если вы используете перечисления, это правильный путь. Вы захотите избежать передачи необработанного значения этого перечисления.

И то, как вы это подтверждаете, тоже кажется прекрасным.


Альтернативой, которая может быть проще, является использование вместо этого объединения строк.

Что-то вроде:

 const rates = ["x-slow", "slow", "medium", "fast", "x-fast"] as const
type Rate = (typeof rates)[number] // "x-slow" | "slow" | "medium" | "fast" | "x-fast"

const arg = 'slow'
console.log(rates.includes(arg)) // true
 

Теперь Rate это один из элементов из элементов rates массива. В типизированных средах вы все равно получаете автозаполнение (хотя это немного менее приятно, чем перечисление).:

автозаполнение союза

В конце концов, это вопрос мнения, и вам решать, каким вы хотите видеть свой API.