Reputation: 4164
I've recently run into a problem of strictly specified allowed strings to be passed into a function:
type TypesList = 'foo' | 'bar' | 'baz';
function send(type: TypesList): void {};
send('foo'); // Ok
send('error'); // Error
Function listed above will only accept one of the three values of TypedList
. What I'm basically trying to do is to provide type union from constant's values so in the case of future modifications I will not be required to update value everywhere.
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
I'm aware of the fact that I could just simply duplicate values from the constant or check in the function but I'm looking for a more cleaner and robust way to handle it.
Upvotes: 3
Views: 1383
Reputation: 30062
String enums are available since TypeScript 2.4.0, which seems to be exactly what you are looking for:
enum Type {
foo = 'foo1',
bar = 'bar2'
}
function send(type: Type): void {};
send(Type.foo);
The enum compiles to a dictionary that maps the key name to the value, for use in run-time. If you don't need that, just make it a const enum
.
Other than that, it is currently not possible to define a type as the union of all values of an object, even when that object is constant. Making a union of strings would be the usual way to go, since the main purpose of making a union of string literal types is to create an enum-like structure with string as their data type. Fortunately, we now have string enums.
As you would be using well-defined constants everywhere, there is also a chance that you do not need such a union type. In that case, you could enclose constants in a namespace and let functions take an ordinary string
:
namespace Types {
export const foo = "foo1";
export const bar = "bar2";
}
function send(type: string): void {};
send(Types.foo);
Upvotes: 2