#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:
Перечисления генерируются компилятором 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.