Why am I getting Typescript Compile Errors at Runtime?

Viewed 441

I have a react component I made in the Visual Studio React + Redux template project with the following "render()" method:

public render() {
        return (
            <React.Fragment>
                <h1>Welcome to the Wayfaring Company {this.props.user?.activeCharacter}!</h1>
    
            </React.Fragment>
        );
    }

The idea is, display one message if the user property (etc.) exists, and another if it does not. When the page loads, it displays: "Welcome to the Wayfaring Company !", then changes to a typescript error screen with:

Failed to compile

./src/components/Splashpage.tsx
Syntax error: Expression expected (34:77)

(Which corresponds to the line with the .? in the render function above)

If I remove the optional chaining operation (the .?) I get a compilation error because user could be undefined. Great. Typescript's doing exactly what we want!

So why does the optional chain cause the code to compile in Visual Studio and fail in the browser? Am I somehow compiling the code to the wrong version of typescript?

Edit: updating to the pre-3.7 style Elvis operator doesn't cause the runtime error, so this does appear to be related to a Typescript versioning problem somehow.

 <h1>Welcome to the Wayfaring Company, {this.props.user!== null && this.props.user!== undefined ? this.props.user.activeCharacter : "Scout"}!</h1>

Still trying to get to the bottom of this -- is IIS somehow running the wrong version of Typescript? I have a very good understanding of the what, but the why (and the how to fix) still elude me.

Is it possible that running this template through visual studio uses a version of Node.js that doesn't support the ?? or .? operators? (I think I'm using Node 12.X)

2 Answers

After more time than I'd prefer to admit, I tracked this down to a Node issue.

Null-coalescing and Optional Chaining were only added in Node 14.X.

After eventually confirming that my local workstation only had Node 12.X installed, all it took was upgrading, deleting node-modules, and restarting the IDE to get to a compile-error free webpage! Hooray!

The discrepancy is that while it is valid Typescript for 3.7+ (so VS compiles it just fine), Node is a wholly separate beast, so there's an invisible incompatibility there that isn't caught until runtime.

You're covering the case where user is not defined but not the case where activeCharacter is not defined. Try this:

{this.props.user?.activeCharacter ?? ''}

This should work because if activeCharacter is undefined as well it will return an empty string (or a string of your choice). Better yet though i wouldn't render the text at all and provide a skeleton ui until you finished retrieving your data (I'm assuming you are waiting for the data to fetch).

Also to answer your question on how can it pass in typescript but not in your browser/production? Well you probably have an interface defined for your user somewhere where you state that activeCharacter is a string or boolean and it is required which is fair, but if you are for example retrieving that user object from an api or external source/db it could be possible that activeCharacter is actually not defined (It would help if the place where you fetch the data from was also strictly typed and written in typescript though to not allow activeCharacter to ever be undefined/null).

Full code example is below.

public render() {
            return (
                <React.Fragment>
                    <h1>Welcome to the Wayfaring Company {this.props.user?.activeCharacter ?? ''}!</h1>
        
                </React.Fragment>
            );
        }
Related