2015-06-11 18 views
9

Nie można ustawić typu parametru na Enum? W ten sposób:Enum as Parametr w maszynie maszynowej

private getRandomElementOfEnum(e : enum):string{ 
    var length:number = Object.keys(e).length; 
    return e[Math.floor((Math.random() * length)+1)]; 
} 

Jeśli to zrobię, Intellij oznaczy ten kod jako nieznany. A proponuję zmienić nazwę zmiennej, czy to ma sens?

private getRandomElementOfEnum(e : any):string{ 
    var length:number = Object.keys(e).length; 
    return e[Math.floor((Math.random() * length)+1)]; 
} 

Kod ten działa bez zarzutu. ale nie jest tak eleganckie i zgodne z kodami.

Czy istnieje możliwość lub małe obejście w celu zdefiniowania wyliczenia jako parametru?

EDIT:

Po zbadaniu tych odpowiedzi, mogę to zrobić również z zestawem ah zdefiniowanego wyliczenia, czegoś podobnego do enum1 | enum2 | enum3?

+2

Czy nie powinno to być 'e: MyEnumType'? Czy chcesz zaakceptować jakiekolwiek wyliczenie? Co by to było dobrego? Możesz także wykonać polecenie 'e: MyEnum | MyOtherEnum | MyThirdEnum'. – Thilo

+0

Powiązane (ale prawdopodobnie nieaktualne): http: // stackoverflow.com/questions/21293063/jak-programowo-wyliczać-a-enum-type-in-maszynopis-0-9-5? rq = 1 – Thilo

+0

każde wyliczenie powinno być możliwe, więc mogę uzyskać losowy element każdego wyliczenia przez wywołanie tej funkcji. – Synoon

Odpowiedz

8

Nie można zagwarantować, że parametr jest wyliczeniem, ponieważ wyliczenia w TS nie dziedziczą ze wspólnego przodka lub interfejsu.

TypeScript wprowadza analizę statyczną. Twój kod używa programowania dynamicznego z Object.keys i e[dynamicKey]. W przypadku kodów dynamicznych wygodny jest typ any.

Twój kod jest błędny: length() nie istnieje, e[Math.floor((Math.random() * length)+1)] zwraca ciąg znaków lub liczbę całkowitą, a the enumeration values can be manually set ...

Oto propozycja:

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)); 

Idealnie, typ parametru any powinny być zastąpiony przez typeof E, ale kompilator (TS 1.5) nie może zrozumieć tej składni.

+0

hehe, mój kod był rzeczywiście buggy, zdałem sobie z tego sprawę około 10 minut później, zapomniałem zmienić kod tutaj .. – Synoon

10

Można to zrobić lepiej niż 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); 
+0

Kompilator zakłada, że ​​'E1' pasuje do typu' {[s: number]: string} ', ale jest to bylina? Obiekt 'E1' zawiera klucze strunowe. – Paleo

+3

Indeksatory liczb nie ograniczają typów nie numerycznych –

3

zgadzam się z @Tarh. Wyliczenia w TypeScript to tylko obiekty JavaScript bez wspólnego interfejsu lub prototypu (a jeśli są to const enum, to nie są nawet obiektami), więc nie można ograniczyć typów do "dowolnego wyliczenia".

Najbliżej mogę dostać coś jak poniżej:

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))]; 
} 

To działa dla wszystkich teksty stałe, ale byłoby również przyjąć inne tablice jako wejście (i nie dlatego, że ciało metoda opiera się na bardzo specyficzny kluczowa struktura, którą mają wyliczenia TypeScript).

Tak więc, o ile nie ma potrzeby korzystania z takiej "ogólnej" funkcji, należy wykonać funkcje bezpiecznego użytkowania dla poszczególnych typów wyliczeniowych (lub typu łączonego, takich jak E1|E2|E3), których faktycznie potrzebujesz.

Jeśli masz taką potrzebę (a może to być problem X-Y, który można rozwiązać w lepszy, zupełnie inny sposób, biorąc pod uwagę więcej kontekstu), użyj any, ponieważ i tak opuściłeś bezpieczne terytorium.

+0

Nie testowałem tej teorii, ale jestem prawie pewien, że twoja implementacja nie obsługuje 'enum E3 {X = 4, Y, Z}. –