Reputation: 4480
New typescript user here.
We often declare our redux actions and other static constants like so (js):
export const notificationTypes = {
WELCOME: "WELCOME",
LOGGED_IN: 'LOGGED_IN',
NEW_EMAIL: 'NEW_EMAIL',
};
I am trying to do the same with typescript:
export const notificationTypes = {
WELCOME: "WELCOME",
LOGGED_IN: 'LOGGED_IN',
NEW_EMAIL: 'NEW_EMAIL',
};
export type NotificationType = keyof typeof notificationTypes;
And here is an attempt to use the new type:
import {notificationTypes, NotificationType} from "./notificationTypes"
interface Notification {
type:NotificationType
}
//no errors
const firstNotificationTest:Notification={
type:"WELCOME"
}
//error type 'string' is not assignable to type "WELCOME" | "LOGGED_IN" | "NEW_EMAIL"
const secondtNotificationTest:Notification={
type:notificationTypes.WELCOME
}
As you can see, I can not use notificationTypes.WELCOME, but rather must use "WELCOME". This somewhat defeats the whole purpose of setting up these constants.
Is it possible to interface Notification
to allow any notificationTypes
value? Or interface notificationTypes
itself so it knows that value = key
? Or am I just using typescript completely wrong here.
Upvotes: 1
Views: 70
Reputation: 74490
You can add a const assertion to narrow down the properties of notificationTypes
to their string literal types.
export const notificationTypes = {
WELCOME: "WELCOME",
LOGGED_IN: 'LOGGED_IN',
NEW_EMAIL: 'NEW_EMAIL',
} as const
This also has the benefit, that the members are marked as readonly
, so something like this cannot happen with normal type usage:
notificationTypes.LOGGED_IN = "duuuhh"
, so you effectively can use notificationTypes
as replacement for a conventional enum.
Upvotes: 3