DEV Community


Discussion on: React Is Eating Itself

bytebodger profile image
Adam Nathaniel Davis Author • Edited

The most common example (IMHO) is on return types. Now, don't get me wrong: I think you can take this concept wayyyy too far. And I'm not saying this should be done all the time - or even most of the time. But it's not terribly uncommon in JS to have getName() return a string if there is just one name, or an array of strings, if there are multiple names.

I know that, in TS, we have union types. Those can help us consume functions that return multiple types. In a "true" statically-typed language, that's not an option. Like, in Java, you can't designate a method as returning a string or an array (although you can accomplish something similar by using generics - which are handled much better in C#).

I often use dynamic typing as a type of semaphore to indicate different stages in a variable's "life cycle". For example, I have a frontend app that has to call to an API to get all of its data. The data sits originally in state values like this:

this.state = {
   roles : false,
   teams : false,
   users : false,

Obviously, the API calls will run asynchronously. And with React's render cycle, it can be tricky to assure that we're not calling the same endpoint for data that we've already received. So in any code that would invoke an API call, there is a check that looks like this:

if (this.state.roles !== false) 

I don't want to set the initial state values to empty objects, because it's at least possible that the API will return an empty object. So then there would be no quick-and-easy way to simply look at the state variables and know whether they've received the API data load.

I could just set the original state values to null. Or I could set additional variables like hasRolesApiBeenCalled and hasRolesApiResponseBeenReceived, but that starts to become a headache. And seeing the false value in my code is a clear visual indicator (to me) that we're checking to see whether anything's been received from the API at all. Because the simple value of false would never be a valid, standalone value received from my API.

Thread Thread
mateiadrielrafael profile image
Matei Adriel • Edited

Heres an example solving the first issue with getName:

type User = {
    name: string

const getName = <T extends User | User[]>(u: T): T extends User ? string : string[] ....implementation

For the semaphore example I dont really get the problem, cant you do somsthing like:

type Semaphore<T> = {
    [K in keyof T]: K[T] | false

I typed those on my phone so idk if I didn't make any typos or stuff, but the logic is there.

Maybe I understood the problems you enumerated wrong, if that's the case than sorry I guess:)

I only used f#, so idk too much about c#, what features do c# generics have you'd like to see in ts?

Thread Thread
bytebodger profile image
Adam Nathaniel Davis Author • Edited

The original question was in regards to where dynamic typing could be "useful" - not required. So from that perspective, there's really nothing to solve in my examples. I'm just explaining to you where dynamic typing can be useful - to me.

Every programming problem can be "solved" with static typing. There is no scenario where we can say, "Well, this particular problem simply can't be solved unless we switch to dynamic typing." (Conversely, every programming problem can also be "solved" with dynamic typing as well.)

What I see in your examples is what I often experience from devs who are firmly ensconced in static typing. They look at every approach that involves dynamic typing and they say, "Why couldn't we do it with static typing this way??" And of course, the answer is always that you could certainly do it that way. And there's certainly nothing wrong with approaching programming tasks through a static-typing lens - just as there's nothing wrong with doing them through dynamic typing.

My only "issue" is that the static-typing crowd tends to look at dynamically-typed languages as though they have a bug or a flaw that they're constantly trying to fix. But dynamic typing isn't a bug in a language. It's a feature.

Now... you may not like that feature. You may prefer to work in languages that don't have that feature. And that's fine. We all have our preferences and our own way of grokking code. But the plain simple truth is that JS is, and has always been, a dynamically-typed language. And there's nothing necessarily "wrong" about that.

If you feel that a particular project is best addressed using TypeScript, then that's cool. I'd probably agree with you. If TypeScript is your go-to tool-of-choice on nearly any project, I wouldn't necessarily agree with you - but I get it. But if you're thinking that JS's dynamic typing is an inherent flaw that needs to be completely washed out of the language, then I'd say you're working in the wrong language. Because dynamic typing wasn't some bug in the language's source code that needs to be "fixed".

Thread Thread
mateiadrielrafael profile image
Matei Adriel • Edited

Fair enough, I now get what you are trying to say:)

A nice approach is the one taken by f# - being statically typed but being able to infer almost everything, but sadly js has a bunch of wild parts which you cannot really infer the result of