`Enum` datilografado da string JSON

Existe alguma maneira de ter uma enumeração TypeScript compatível com seqüências de caracteres de JSON?

Por exemplo:

enum Type { NEW, OLD }

interface Thing { type: Type }

let thing:Thing = JSON.parse('{"type": "NEW"}');

alert(thing.type == Type.NEW); // false

Eu gostariagostar thing.type == Type.NEW ser verdadeiro. Ou, mais especificamente, gostaria de poder especificar oenum valores a serem definidos comocordas, não números.

Estou ciente de que posso usarthing.type.toString() == Type[Type.NEW] mas isso é complicado e parece tornar a anotação do tipo enum confusa e enganosa, o que anula seu objetivo. O JSON é tecnicamentenão fornecendo um valor de enum válido, portanto, não devo digitar a propriedade no enum.

Então, o que estou fazendo atualmente é usar um tipo de string com constantes estáticas:

const Type = { NEW: "NEW", OLD: "OLD" }

interface Thing { type: string }

let thing:Thing = JSON.parse('{"type": "NEW"}');

alert(thing.type == Type.NEW); // true

Isso me dá o uso que eu quero, mas a anotação de tipostring é muito amplo e propenso a erros.

Estou um pouco surpreso que um superconjunto de JavaScript não tenha enumerações baseadas em string. Estou esquecendo de algo? Existe uma maneira diferente de fazer isso?

Atualizar TS 1.8

Usandotipos literais de string é outra alternativa (obrigado @basaret), mas para obter o uso desejado do tipo enum (acima), é necessário definir seus valoresduas vezes: uma vez em um tipo literal de sequência e uma vez como um valor (constante ou espaço para nome):

type Type = "NEW" | "OLD";
const Type = {
    NEW: "NEW" as Type,
    OLD: "OLD" as Type
}

interface Thing { type: Type }

let thing:Thing = JSON.parse(`{"type": "NEW"}`);

alert(thing.type === Type.NEW); // true

Isso funciona, mas exige muito clichê, o suficiente para eu não usá-lo na maioria das vezes. Por enquanto, espero que oproposta parastring enums acabará por fazer o roteiro.

Atualizar TS 2.1

O novokeyof pesquisa de tipo permite que o tipo literal de string seja gerado a partir das chaves de uma const ou namespace, o que torna a definição umapouco menos redundante:

namespace Type {
    export const OLD = "OLD";
    export const NEW = "NEW";
}
type Type = keyof typeof Type;

interface Thing { type: Type }

const thing: Thing = JSON.parse('{"type": "NEW"}');
thing.type == Type.NEW // true

Atualizar TS 2.4

O TypeScript 2.4 adicionou suporte para enumerações de strings! O exemplo acima se torna:

enum Type {
    OLD = "OLD",
    NEW = "NEW"
}

interface Thing { type: Type }
const thing: Thing = JSON.parse('{"type": "NEW"}');
alert(thing.type == Type.NEW) // true

Isso parecepor pouco perfeito, mas ainda há alguma mágoa:

Vocêainda tem que escrever o valor duas vezes, ou sejaOLD = "OLD", e não há validação de que você não possui um erro de digitação, comoNEW = "MEW"... isso já me picou em código real.

Existem algumas peculiaridades (talvez bugs?) Com a forma como o enum é verificado por tipo, não é apenas uma abreviação de tipo literal de string, que é o que seria realmente correto. Alguns problemas com que me deparei:

enum Color { RED = "RED", BLUE = "BLUE", GREEN = "GREEN" }

type ColorMap = { [P in Color]: number; }

declare const color: Color;
declare const map: ColorMap;
map[color] // Error: Element implicitly has an 'any' type because type 'ColorMap' has no index signature.

const red: Color = "RED"; // Type '"RED"' is not assignable to type 'Color'.
const blue: Color = "BLUE" as "RED" | "BLUE" | "GREEN"; // Error: Type '"RED" | "BLUE" | "GREEN"' is not assignable to type 'Color'.

O código equivalente comenum Color substituído por tipos literais de string funciona bem ...

Sim, acho que tenho TOC sobre isso, só quero minhas enumerações JS perfeitas. :)

questionAnswers(4)

yourAnswerToTheQuestion