Перечисление в качестве параметра в TypeScript
разве невозможно установить тип параметра в перечисление? Вот так:
private getRandomElementOfEnum(e : enum):string{
var length:number = Object.keys(e).length;
return e[Math.floor((Math.random() * length)+1)];
}
Если я это сделаю, Intellij пометит этот код как неизвестный. И предложите переименовать переменную, это имеет смысл?
private getRandomElementOfEnum(e : any):string{
var length:number = Object.keys(e).length;
return e[Math.floor((Math.random() * length)+1)];
}
этот код работает нормально. но это не так элегантно и условно.
есть ли возможность или небольшое обходное решение для определения перечисления в качестве параметра?
EDIT:
после изучения этих ответов, могу ли я сделать это также с AH набором определенного перечисления, sth похож на enum1|enum2 / enum3?
3 ответов
невозможно гарантировать, что параметр является перечислением, потому что перечисления в TS не наследуются от общего предка или интерфейса.
TypeScript приносит статический анализ. Ваш код использует динамическое программирование с Object.keys
и e[dynamicKey]
. Для динамических кодов введите any
удобно.
ваш код глючит:length()
не существует, e[Math.floor((Math.random() * length)+1)]
возвращает строку или целое число, а значения перечисления могут быть вручную set...
вот это предложение:
function getRandomElementOfEnum<E>(e: any): E {
var keys = Object.keys(e),
index = Math.floor(Math.random() * keys.length),
k = keys[index];
if (typeof e[k] === 'number')
return <any>e[k];
return <any>parseInt(k, 10);
}
function display(a: Color) {
console.log(a);
}
enum Color { Blue, Green };
display(getRandomElementOfEnum<Color>(Color));
в идеале, параметр типа any
следует заменить на typeof E
но компилятор (TS 1.5) не может понять этот синтаксис.
Вы можете сделать лучше, чем any
:
enum E1 {
A, B, C
}
enum E2 {
X, Y, Z
}
function getRandomElementOfEnum(e: { [s: number]: string }): number {
/* insert working implementation here */
return undefined;
}
// OK
var x: E1 = getRandomElementOfEnum(E1);
// Error
var y: E2 = getRandomElementOfEnum(window);
// Error
var z: string = getRandomElementOfEnum(E2);
Я согласен с @Tarh. Перечисления в TypeScript - это просто объекты Javascript без общего интерфейса или прототипа (и если они const enum
, тогда они даже не являются объектами), поэтому вы не можете ограничить типы "любым перечислением".
ближе всего я мог бы получить что-то вроде следующего:
enum E1 {
A, B, C
}
enum E2 {
X, Y, Z
}
// make up your own interface to match TypeScript enums
// as closely as possible (not perfect, though)
interface Enum {
[id: number]: string
}
function getRandomElementOfEnum(e: Enum): string {
let length = Object.keys(e).length / 2;
return e[Math.floor((Math.random() * length))];
}
это работает для всех перечислений, но он также принимает другие массивы в качестве входных данных (а затем терпит неудачу, потому что тело метода полагается на очень конкретную ключевую структуру, которую перечисляет TypeScript иметь.)
поэтому, если у вас нет реальной необходимости в такой "общей" функции, сделайте функции typesafe для отдельных типов перечисления (или типа объединения, например E1|E2|E3
), что вам действительно нужно.
и если у вас есть эта потребность (и это вполне может быть X-Y-проблема, которая может быть решена лучше, совершенно по-другому, учитывая больше контекста), используйте any
, потому что вы все равно покинули территорию безопасной.