In a React project I am using a type guard to ensure I am passing down a prop that has the appropriate type. This seems to work because TypeScript is not raising any error in my IDE. But when running type-check as a command, the compiler fails on that prop.
I have a component that is rendering a child component. That child component needs to receive a prop with a custom type, declared in an enum AuthorizedType. To ensure that the prop passed is valid, I created a type guard isAuthorizedType. If the type is not valid, the component won't render.
Because the child component is not rendered when the type guard is failing, TypeScript is not raising any error in my IDE. But when running type-check as a command, the compiler raises the error:
TS2322: Type 'string' is not assignable to type 'AuthorizedType'.
I wonder why is the error not raised in the IDE but raised when running type-checking. I understand that type guards perform a runtime check, and I wonder what it means exactly and if that's related.
Here is the code:
// ParentComponent.tsx
export enum AuthorizedType {
First = 'first',
Second = 'second',
}
function isAuthorizedType(value: any): value is AuthorizedType {
return Object.values(AuthorizedType).indexOf(value) !== -1;
}
function ParentComponent({value}: {value: string}) {
const isValidType = isAuthorizedType(value);
if (!isValidType) {
return null;
}
return (<ChildComponent value={value} />)
}
// ChildComponent.tsx
import {AuthorizedType} from '..';
function ChildComponent({value}: {value: AuthorizedType}) {
switch(value) {
case AuthorizedType.First:
return <div>first</div>
case AuthorizedType.Second:
return <div>second</div>
}
}
By moving the type guard into the child component, type-check is not raising any error anymore:
// ChildComponent.tsx
import {AuthorizedType} from '..';
function isAuthorizedType(value: any): value is AuthorizedType {
return Object.values(AuthorizedType).indexOf(value) !== -1;
}
function ChildComponent({value}: {value: string}) {
const isValidType = isAuthorizedType(value);
if (!isValidType) {
return null;
}
switch(value) {
case AuthorizedType.First:
return <div>first</div>
case AuthorizedType.Second:
return <div>second</div>
}
}
I would like to understand why.