I have this type definition in TypeScript:
export type xhrTypes = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"OPTIONS\" | \"CONNECT\" | \"HEAD\";
While not the types that were asked for, if an enum would be okay then the following can be used for case-insensitive matching of enum string values:
/**
* Gets an enumeration given a case-insensitive key. For a numeric enum this uses
* its members' names; for a string enum this searches the specific string values.
* Logs a warning if the letter case was ignored to find a match, and logs an error
* including the supported values if no match was found.
*/
static toEnumIgnoreCase(target: T, caseInsentiveKey: string): T[keyof T] {
const needle = caseInsentiveKey.toLowerCase();
// If the enum Object does not have a key "0", then assume a string enum
const key = Object.keys(target)
.find(k => (target['0'] ? k : target[k]).toLowerCase() === needle);
if (!key) {
const expected = Object.keys(target)
.map(k => target['0'] ? k : target[k])
.filter(k => isNaN(Number.parseInt(k)))
.join(', ');
console.error(`Could not map '${caseInsentiveKey}' to values ${expected}`);
return undefined;
}
const name = target['0'] ? key : target[key];
if (name !== caseInsentiveKey) {
console.warn(`Ignored case to map ${caseInsentiveKey} to value ${name}`);
}
return target[key];
}
Of course, as this loops over possible values, it's really only meant to handle things like configuration files; all code should really use the enum
values instead.
Some tests:
import Spy = jasmine.Spy;
import {ConfigHelper} from './config-helper';
// Should match on One, one, ONE and all:
enum NumberEnum { One, Two, Three }
// Should match on Uno, uno, UNO and all, but NOT on One, one, ONE and all:
enum StringEnum { One = 'Uno', Two = 'Dos', Three = 'Tres' }
describe('toEnumIgnoreCase', () => {
beforeEach(function () {
spyOn(console, 'warn');
spyOn(console, 'error');
});
it('should find exact match for numeric enum', () => {
const result = ConfigHelper.toEnumIgnoreCase(NumberEnum, 'One');
expect(result).toBe(NumberEnum.One);
expect(console.warn).not.toHaveBeenCalled();
expect(console.error).not.toHaveBeenCalled();
});
it('should find case-insensitive match for numeric enum', () => {
const result = ConfigHelper.toEnumIgnoreCase(NumberEnum, 'two');
expect(result).toBe(NumberEnum.Two);
expect(console.warn).toHaveBeenCalled();
expect((console.warn as Spy).calls.mostRecent().args[0])
.toMatch(/value Two/);
expect(console.error).not.toHaveBeenCalled();
});
it('should yield undefined for non-match for numeric enum', () => {
const result = ConfigHelper.toEnumIgnoreCase(NumberEnum, 'none');
expect(result).toBe(undefined);
expect(console.warn).not.toHaveBeenCalled();
expect(console.error).toHaveBeenCalled();
expect((console.error as Spy).calls.mostRecent().args[0])
.toMatch(/values One, Two, Three/);
});
it('should find exact match for string enum', () => {
const result = ConfigHelper.toEnumIgnoreCase(StringEnum, 'Uno');
expect(result).toBe(StringEnum.One);
expect(console.warn).not.toHaveBeenCalled();
expect(console.error).not.toHaveBeenCalled();
});
it('should find case-insensitive match for string enum', () => {
const result = ConfigHelper.toEnumIgnoreCase(StringEnum, 'dos');
expect(result).toBe(StringEnum.Two);
expect(console.warn).toHaveBeenCalled();
expect((console.warn as Spy).calls.mostRecent().args[0])
.toMatch(/value Dos/);
expect(console.error).not.toHaveBeenCalled();
});
it('should yield undefined for name rather than string value', () => {
const result = ConfigHelper.toEnumIgnoreCase(StringEnum, 'One');
expect(result).toBe(undefined);
expect(console.warn).not.toHaveBeenCalled();
expect(console.error).toHaveBeenCalled();
expect((console.error as Spy).calls.mostRecent().args[0])
.toMatch(/values Uno, Dos, Tres/);
});
it('should yield undefined for non-match for string enum', () => {
const result = ConfigHelper.toEnumIgnoreCase(StringEnum, 'none');
expect(result).toBe(undefined);
expect(console.warn).not.toHaveBeenCalled();
expect(console.error).toHaveBeenCalled();
expect((console.error as Spy).calls.mostRecent().args[0])
.toMatch(/values Uno, Dos, Tres/);
});
});