I am trying to implement constants in interface, but dont know why it gives error while acessing data
in switch case.
If I use just string
in interface
instead of constants APP_STATUS
then it works fine.
Example:
//Gives error
interface InconsistenciesData {
type: typeof APP_STATUS.INCONSISTENCIES;
data: Inconsistency[];
}
//Works fine
interface InconsistenciesData {
type: 'INCONSISTENCIES';
data: Inconsistency[];
}
Below are my code snippets.
types.ts
export const APP_STATUS = {
CONFIRMED: 'CONFIRMED',
INCONSISTENCIES: 'INCONSISTENCIES',
SUCCESS: 'SUCCESS',
ERROR: 'ERROR',
LOADING: 'LOADING',
OK: 'OK'
}
interface InconsistenciesLoading {
type: typeof APP_STATUS.LOADING;
}
interface InconsistenciesError {
type: typeof APP_STATUS.ERROR;
}
interface InconsistenciesSuccess {
type: typeof APP_STATUS.SUCCESS;
}
interface InconsistenciesData {
type: typeof APP_STATUS.INCONSISTENCIES;
data: Inconsistency[];
}
export type ViewState = InconsistenciesData | InconsistenciesSuccess | InconsistenciesLoading | InconsistenciesError;
My react component
const [viewState, setViewState] = useState<ViewState>({type: APP_STATUS.LOADING})
const renderPageContent = () => {
switch (viewState.type) {
case APP_STATUS.INCONSISTENCIES:
return <InconsistenciesTable inconsistencies={viewState.data} /> //Error: Property 'data' does not exist on type 'ViewState'. Property 'data' does not exist on type 'InconsistenciesSuccess'.
case APP_STATUS.ERROR:
return <Forbidden />
case APP_STATUS.SUCCESS:
return <ThankYouContent />
case APP_STATUS.LOADING:
return <Loading />
}
}
CodePudding user response:
Just replace your object with an enum, that's what they're for:
export enum APP_STATUS {
CONFIRMED,
INCONSISTENCIES,
SUCCESS,
ERROR,
LOADING,
OK,
}
export interface Inconsistency {};
export interface InconsistenciesLoading {
type: APP_STATUS.LOADING;
}
export interface InconsistenciesError {
type: APP_STATUS.ERROR;
}
export interface InconsistenciesSuccess {
type: APP_STATUS.SUCCESS;
}
export interface InconsistenciesData {
type: APP_STATUS.INCONSISTENCIES;
data: Inconsistency[];
}
type ViewState = InconsistenciesData | InconsistenciesSuccess | InconsistenciesLoading | InconsistenciesError;
export const component = ({ state }: { state: ViewState }) => {
switch (state.type) {
case APP_STATUS.INCONSISTENCIES:
console.log(state.data); // Look ma, no error!
}
};
Your version fails because unlike an enum your APP_STATE
constant is actually just a regular mutable object: there's no guarantee that your compile-time type will still hold when the switch statement actually takes effect at runtime.
CodePudding user response:
export enum APP_STATUS {
CONFIRMED = 'CONFIRMED',
INCONSISTENCIES = 'INCONSISTENCIES',
SUCCESS = 'SUCCESS',
ERROR = 'ERROR',
LOADING = 'LOADING',
OK = 'OK'
}
export interface Inconsistency {};
export interface InconsistenciesLoading {
type: APP_STATUS.LOADING;
}
export interface InconsistenciesError {
type: APP_STATUS.ERROR;
}
export interface InconsistenciesSuccess {
type: APP_STATUS.SUCCESS;
}
export interface InconsistenciesData {
type: APP_STATUS.INCONSISTENCIES;
data: Inconsistency[];
}
type ViewState = InconsistenciesData | InconsistenciesSuccess | InconsistenciesLoading | InconsistenciesError;
I have added String enums, becuase I was using these status in other files also, like:
if(response.status === APP_STATUS.SUCCESS) {
//code
}