typescript - Tipo a partir dos valores de um objeto
Recentemente encontrei um problema de strings estritamente especificadas que podem ser passadas para uma função:
type TypesList = 'foo' | 'bar' | 'baz';
function send(type: TypesList): void {};
send('foo'); // Ok
send('error'); // Error
A função listada acima aceitará apenas um dos três valores de TypedList. O que eu basicamente estou tentando fazer é fornecer uma união de tipos a partir dos valores constantes para que, no caso de modificações futuras, eu não seja obrigado a atualizar o valor em todos os lugares.
const types = {
foo: 'foo1',
bar: 'bar2'
};
// Will check for "foo | bar" but I need "foo1 | bar2"
type TypesList = keyof typeof types;
function send(type: TypesList): void {};
send(types.foo); // Invalid
Estou ciente do fato de que eu poderia simplesmente duplicar valores da constante ou verificar na função, mas estou procurando uma maneira mais limpa e robusta de lidar com isso.
Resposta #1
Enums de string estão disponíveis desde o TypeScript 2.4.0, o que parece ser exatamente o que você está procurando:
enum Type {
foo = 'foo1',
bar = 'bar2'
}
function send(type: Type): void {};
send(Type.foo);
O enum compila para um dicionário que mapeia o nome da chave para o valor, para uso em tempo de execução. Se você não precisar disso, apenas transforme-o em um const enum.
Além disso, atualmente não é possível definir um tipo como a união de todos os valores de um objeto, mesmo quando esse objeto é constante. Fazer uma união de strings seria a maneira usual de proceder, pois o principal objetivo de criar uma união de tipos literais de string é criar uma estrutura semelhante a um enum com string como seu tipo de dado. Felizmente, agora temos enums de string.
Como você estaria usando constantes bem definidas em todos os lugares, também há a chance de que você não precise de um tipo de união desse tipo. Nesse caso, você poderia colocar as constantes em um namespace e deixar que as funções recebam uma string comum:
namespace Types {
export const foo = "foo1";
export const bar = "bar2";
}
function send(type: string): void {};
send(Types.foo);
