DEV Community

Discussion on: Key Headaches in TypeScript

Collapse
 
psiho profile image
Mirko Vukušić

Oh I can feel your pain. Just converted my first project from js to ts and my initial feeling was exactly like that. Not just with generics but also with with "variable can be null" when it actually cannot. But relatively simple logic was not "understood" by ts which made me write extra code just to make it clear to the compiler. But I did discover some very old bugs as soon as I converted, even some of those "cannot be reproduced" hard to fix issues. On the other hands I've run into new ones, in type definitions for some libraries which work perfectly ok in js (i.e. when string or number does not matter as it is output only to HTML) but I have to add extra code for ts also to like it. Bottom line, code completion alone is worth it so I'm sticking with it. But first impression is that I dont "love it", I just have to deal with it.

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

Not just with generics but also with with "variable can be null" when it actually cannot.

I appreciate all of your feedback, but this particular line really struck me. I kinda ran into the same issue in my previous articles on defaultProps in React/TS. I had a situation like this:

interface Props {
   name?: string
}

const soSomething: React.FC<Props> = (props: Props) => {
   if (props.name === undefined) props.name = 'default';

   const getNameLetters = () => {
      return props.name.split('');
   }

   return <></>;
}

But TS complains about props.name.split(''); because it says that props.name could be undefined. It does this because defining the name in the interface as name?: string gives props.name a type of string | undefined.

Of course, any first-year dev can look at that code for 1 minute and realize that props.name will never be undefined. It can't be. Because if it was passed in as undefined, the logic at the top of the function will set a default value for it. But even though the first-year dev easily understands this, TS can't grasp it. So I get that ugly ol' "red squiggly" under the code.

Arrrggghhhh...

Collapse
 
psiho profile image
Mirko Vukušić

Yeah, now move that if (props.name === undefined) props.name = 'default'; down inside getNameLetters, just before return and it works! Obviously, TS expects getNameLetters() can be used in different scenarios, sometimes without setting props.name it to default. But if this is your complete app or your only call to to the func, it looks funny. Some say we cannot expect TS to get some compex login and I agree. Devs cannot either, at a glance, so it's good practice to typeguard anyway in those cases. However, some cases appear to me to be really simple and I feel I'm writing a boilerplate to make kids understand it.
However, again to defense of TS, I had the same opinion in similar case, and I was wrong :) It is similar issue but now inside async callback function. Well, value can be changed in the meantime, while async function is running. Was also complaining about writing typeguards only to discover a nasty bug for not doing so in the first place.