Reputation: 1782
I have an array of static strings that I want to create an interface off of. The best way to explain this is to show an example of psedo-interfaces:
const types = ["error", "warning", "success"];
interface Modal {
type: keyof types;
}
I need to use the types, in order, in my actual js so I was hoping there was a way to express this in the interface so I don't have to duplicate the values in the array and the interface. Is this possible?
Upvotes: 2
Views: 371
Reputation: 327819
You can get this, but the problem is that types
is widened to string[]
, which loses the information about which specific strings are in the array, and in which order.
If all you want is the particular strings and don't care about the order, you can make a helper function which uses a trick to get types
to be inferred as a narrower type (you can read this issue for more info about how to prevent widening):
const narrowArray = <K extends string>(...arr: K[]) => arr;
And use it:
const types = narrowArray("error", "warning", "success");
Now types
is inferred to be Array<"error"|"warning"|"success">
. If you want Modal['types']
to be one of those strings (not clear from your post... keyof
certainly won't do it), then you can do this:
interface Modal {
type: (typeof types)[number]; // "error" | "warning" | "success"
}
That should work for you.
Also relevant: starting in TypeScript 3.0 there will be a way to infer tuple types which will let you keep track of the ordering of types
as well. It will be like this:
// only works in TS3.0 and up
const narrowTuple = <K extends string[]>(...arr: K) => arr;
const types = narrowTuple("error", "warning", "success");
// types is inferred as type ["error", "warning", "success"]
Now types
is inferred as the triple ["error", "warning", "success"]
, and so at compile time TypeScript will know that, for example, types[1]
is specifically "warning"
. (You don't need to keep track of ordering for the Modal['type']
definition above, unless I'm not understanding what you want Modal['type']
to be.)
Hope that helps. Good luck!
Upvotes: 7
Reputation: 189
Sorry there is no way to dynamically create an interface at run time. It would defeat the whole purpose of static typing.
You could however do something like this:
export enum StatusCodes {
error = 'error,
success = 'success',
warning = 'warning'
}
const types: Array<StatusCodes> = [StatusCodes.error, StatusCodes.success, StatusCodes.warning]
interface Modal {
type: StatusCodes
}
Upvotes: 3