Jak utworzyć typ wyliczeniowy w języku TypeScript?

121

Pracuję nad plikiem definicji dla Google Maps API dla TypeScript.

I muszę zdefiniować typ wyliczeniowy, np. google.maps.Animationktóry zawiera dwie właściwości: BOUNCEi DROP.

Jak należy to zrobić w języku TypeScript?

eNepper
źródło
3
Definicja Google Maps v3 jest już kompletna i można ją znaleźć na Github i NuGet
eNepper

Odpowiedzi:

141

TypeScript 0.9+ ma specyfikację wyliczeń:

enum AnimationType {
    BOUNCE,
    DROP,
}

Ostatni przecinek jest opcjonalny.

Steve Lucco
źródło
11
Odradzałbym używanie tej enumkonstrukcji na tym etapie, ponieważ zespół TypeScript jasno dał do zrozumienia, że ​​to się zmieni - więc się zepsuje.
Fenton
1
Rozgość się z narzędziami do edycji, na przykład kodem, który dodajesz do odpowiedzi. Zmieniłem to w twojej odpowiedzi na, spójrz proszę. Proszę również zostawić odniesienie, jeśli istnieje powiązana dyskusja na temat tej funkcji języka.
hakre
enum Animation {BOUNCE = 1, DROP}, ponieważ tak definiuje API Map Google.
dchest
30
Do Twojej wiadomości, TypeScript 0.9 zawiera sfinalizowany projekt
wyliczeń
Wyliczenie i jego konwencje nazewnictwa elementów członkowskich są takie same jak w języku C #. (oba od firmy Microsoft). To PascalCase. Nie UPPER_CASE.
Dominik
67

Począwszy od TypeScript 0.9 (obecnie wersja alfa) możesz użyć definicji wyliczenia w następujący sposób:

enum TShirtSize {
  Small,
  Medium,
  Large
}

var mySize = TShirtSize.Large;

Domyślnie tym wyliczeniom zostaną przypisane odpowiednio 0, 1 i 2. Jeśli chcesz jawnie ustawić te liczby, możesz to zrobić w ramach deklaracji wyliczenia.

Listing 6.2 Wyliczenia z jawnymi członkami

enum TShirtSize {
  Small = 3,
  Medium = 5,
  Large = 8
}

var mySize = TShirtSize.Large;

Oba te przykłady pochodzą bezpośrednio z TypeScript for JavaScript Programmers .

Zauważ, że różni się to od specyfikacji 0.8. Specyfikacja 0.8 wyglądała tak - ale została oznaczona jako eksperymentalna i prawdopodobnie ulegnie zmianie, więc będziesz musiał zaktualizować stary kod:

Zastrzeżenie - ten przykład 0.8 byłby uszkodzony w nowszych wersjach kompilatora TypeScript.

enum TShirtSize {
  Small: 3,
  Medium: 5,
  Large: 8
}

var mySize = TShirtSize.Large;
Fenton
źródło
3
To powinna być teraz akceptowana odpowiedź, ponieważ nadal działa w RC i dlatego jest mało prawdopodobne, aby zepsuła z przyszłymi wersjami TS.
Adrian Grigore,
24

To jest teraz częścią języka. Zobacz TypeScriptLang.org> Basic Types> enum, aby uzyskać dokumentację na ten temat. Fragment dokumentacji na temat korzystania z tych wyliczeń:

enum Color {Red, Green, Blue};
var c: Color = Color.Green;

Lub z ręcznymi numerami podkładowymi:

enum Color {Red = 1, Green = 2, Blue = 4};
var c: Color = Color.Green;

Możesz również wrócić do nazwy wyliczenia, używając na przykład Color[2].

Oto przykład tego, jak to wszystko idzie razem:

module myModule {
    export enum Color {Red, Green, Blue};

    export class MyClass {
        myColor: Color;

        constructor() {
            console.log(this.myColor);
            this.myColor = Color.Blue;
            console.log(this.myColor);
            console.log(Color[this.myColor]);
        }
    }
}

var foo = new myModule.MyClass();

Spowoduje to zarejestrowanie:

undefined  
2  
Blue

Ponieważ w momencie pisania tego, Playground Typescript wygeneruje następujący kod:

var myModule;
(function (myModule) {
    (function (Color) {
        Color[Color["Red"] = 0] = "Red";
        Color[Color["Green"] = 1] = "Green";
        Color[Color["Blue"] = 2] = "Blue";
    })(myModule.Color || (myModule.Color = {}));
    var Color = myModule.Color;
    ;
    var MyClass = (function () {
        function MyClass() {
            console.log(this.myColor);
            this.myColor = Color.Blue;
            console.log(this.myColor);
            console.log(Color[this.myColor]);
        }
        return MyClass;
    })();
    myModule.MyClass = MyClass;
})(myModule || (myModule = {}));
var foo = new myModule.MyClass();
Jeroen
źródło
14

Jeszcze jedna uwaga, że ​​możesz wyliczyć identyfikator / ciąg za pomocą następującego:

class EnumyObjects{
    public static BOUNCE={str:"Bounce",id:1};
    public static DROP={str:"Drop",id:2};
    public static FALL={str:"Fall",id:3};


}
done_merson
źródło
2
Jak uzyskać do nich dostęp stri idkorzystając z tego?
kba
1
EnumyObjects.BOUNCE.str uzyskałby dostęp do wartości.
done_merson
2
Problem z tym projektem polega na tym, że wszystkie obiekty są zmienne, co może powodować problemy: goo.gl/CT4Ip
Fenton
Byłoby abstract classbardziej odpowiednie, aby zapobiec tworzeniu wystąpień, ponieważ TypeScript nie ma pojęcia static class?
wesoły
10

Aktualizacja :

Jak zauważył @ iX3, Typescript 2.4 obsługuje ciągi wyliczeniowe.

Zobacz: Tworzenie wyliczenia z wartościami ciągów w skrypcie Typescript


Oryginalna odpowiedź:

W przypadku wartości składowych typu String język TypeScript dopuszcza tylko liczby jako wartości elementu członkowskiego wyliczenia. Ale jest kilka rozwiązań / hacków, które możesz wdrożyć;

Rozwiązanie 1:

skopiowane z: https://blog.rsuter.com/how-to-implement-an-enum-with-string-values-in-typescript/

Jest proste rozwiązanie: przed przypisaniem wystarczy rzutować literał ciągu na dowolny:

export enum Language {
    English = <any>"English",
    German = <any>"German",
    French = <any>"French",
    Italian = <any>"Italian"
}

rozwiązanie 2:

skopiowane z: https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html

Możesz użyć literału ciągu jako typu. Na przykład:

let foo: 'Hello';

Tutaj stworzyliśmy zmienną o nazwie foo, która pozwoli na przypisanie jej tylko wartości literalnej „Hello”. Przedstawiono to poniżej:

let foo: 'Hello';
foo = 'Bar'; // Error: "Bar" is not assignable to type "Hello"

Same w sobie nie są zbyt przydatne, ale można je łączyć w unię typów, aby stworzyć potężną (i przydatną) abstrakcję, np .:

type CardinalDirection =
    "North"
    | "East"
    | "South"
    | "West";

function move(distance: number, direction: CardinalDirection) {
    // ...
}

move(1,"North"); // Okay
move(1,"Nurth"); // Error!
Arthur
źródło
1
TypeScript 2.4 obejmuje obsługę typów literałów ciągów w wyliczeniach. Zobacz stackoverflow.com/questions/15490560/… i blogs.msdn.microsoft.com/typescript/2017/06/27/…
iX3
1

Wyliczenia w maszynie:

Wyliczenia są umieszczane w języku maszynopisu w celu zdefiniowania zestawu nazwanych stałych. Używanie wyliczeń może ułatwić nam życie. Powodem tego jest to, że te stałe są często łatwiejsze do odczytania niż wartość, którą reprezentuje wyliczenie.

Tworzenie wyliczenia:

enum Direction {
    Up = 1,
    Down,
    Left,
    Right,
}

Ten przykład z dokumentacji maszynopisu bardzo ładnie wyjaśnia, jak działają wyliczenia. Zwróć uwagę, że nasza pierwsza wartość wyliczenia (Up) jest inicjalizowana z wartością 1. Wszystkie kolejne elementy składowe wyliczenia liczby są następnie automatycznie zwiększane z tej wartości (tj. W dół = 2, w lewo = 3, w prawo = 4). Gdybyśmy nie zainicjowali pierwszej wartości wartością 1, wyliczenie zaczynałoby się od 0, a następnie automatycznie zwiększało (tj. W dół = 1, w lewo = 2, w prawo = 3).

Korzystanie z wyliczenia:

Możemy uzyskać dostęp do wartości wyliczenia w następujący sposób:

Direction.Up;     // first the enum name, then the dot operator followed by the enum value
Direction.Down;

Zauważ, że w ten sposób jesteśmy o wiele bardziej opisowy w sposób piszemy nasz kod. Wyliczenia zasadniczo uniemożliwiają nam używanie liczb magicznych (liczb, które reprezentują jakąś jednostkę, ponieważ programista nadał im znaczenie w pewnym kontekście). Liczby magiczne są złe z następujących powodów:

  1. Musimy się bardziej zastanowić, najpierw musimy przetłumaczyć liczbę na jednostkę, zanim będziemy mogli uzasadnić nasz kod.
  2. Jeśli po dłuższej chwili przejrzymy nasz kod lub inni programiści przejrzą nasz kod, niekoniecznie wiedzą, co oznaczają te liczby.
Willem van der Veen
źródło