Перечисление в качестве параметра в 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, потому что вы все равно покинули территорию безопасной.