Hey there!
Special thanks to anyone that filled out the survey from the last email! One of the top results was TypeScript. So, guess what this week’s issue is all about?! … TypeScript! Following the typical( — after 1 issue can it be called typical?!) Broken Comb format, let’s go wide and deep. Even though we’ll start with 101, hopefully, there’s something here for everyone.
Also! If you didn’t vote there’s still time and I would love your feedback.
Lately, I’ve been experimenting with Laravel. That’s right. Let me explain (and I’ll don’t worry, this comes back to TypeScript.) In the JavaScript ecosystem, we LOVE being composable. We love that we can configure our stack to be whatever we want it to be. You do you!
But, lately…
(The shades of red even match! 😂*)*
But lately, stuff within the JavaScript ecosystem has just been … hard. Each project comes with it’s own decision fatigue. As much as we say celebrate our custom stack and composability, there is something nice about someone making those decisions for you. “This is the way.” — and then it just works! (This has always been part of the appeal for me with RedwoodJS. It’s opinionated!)
So, I thought, “I’m a lead maintainer on the RedwoodJS core team. People say they want the Laravel framework for JavaScript. What does that mean?” The only way to figure that out is to build something on Laravel and see what it has that we don’t.
During this process, I realized a couple of things.
1️⃣ There are two ways to approach development.
(1) Front to back. Start with the page design. Build out what your user sees and determine how they’ll will interact with your application. Then, let that inform your backend. At that point, you’ll know exactly what data you need where. JavaScript shines here.
(2) Back to front. Start with the API. The data is king. Without the data, what is your application really? Do all the heavy lifting first. Then, when it comes time to getting it on the page, you’re working with real datasets. Laravel is the hero here.
I see the value in both approaches. I’m not sure if it’s my background in design and frontend, but I prefer the first method.
2️⃣ There’s tremendous value in using a single language. I’m not sure if it’s the learning curve and things would get easier with experience, but when I was using Laravel I struggled moving from PHP → Blade (templating language) → to Livewire (think RSCs) → to Alpine (simplified JavaScript). That’s 4 different levels! 🤯 and the syntax is slightly different with each.
But, the straw that broke the camel’s back, was TYPESCRIPT! (I told you I would come around!)
PHP is a Typed language. It knows if you’re using a string or a number and won’t let you mix and match. PHP is a dynamically typed language, which means there is no need to tell it “This is a number,” it just knows.

JavaScript is not typed at all. You can have a variable that starts off as number and then turn it into a string. Tricky. This is one of JavaScript’s biggest criticisms. But, this is also one of the things that I love the most about JavaScript. It’s forgiving. It’s going to try it’s best to keep running. Semicolons, whatever.
TypeScript has been the response to some of those criticisms. It puts guard rails around JavaScript.
It makes me giggle a little bit when people call TypeScript a language. I mean it is, but it isn’t.
At its core, TypeScript is a superset of JavaScript. _ from Getting Started with TypeScript: A Comprehensive Guide for Beginners
You can think of TypeScript like adjectives. It’s just describing your variables. And TypeScript will point out when your descriptions and implementations aren’t consistent.
Let me tie this back into the Laravel project I tried to build. I had a database of users. Every user has a unique ID: 1, 2, 3, 4, etc. Straightforward enough. I seeded the database with a few users and explicitly said, “This user’s ID is “1”, this user’s ID is “2”. Maybe you already see where this is going?
Then, when I created a new user, I generated a unique UUID for an ID. (UUID stands for universally unique identifier and looks like a gross string, acde070d-8c4c-4f0d-9d8a-162843c10333) Simple enough. 🤪
The problem was all my seeded data worked perfectly because even though it was a string, it also happened to be a number. Any new user I created had problems because it couldn’t convert acde070d-8c4c-4f0d-9d8a-162843c10333 to a number. (Well, technically, you can, but it might return an error that says the ID is too large for database)
This bug made it’s way into production 😱 It looked like new users could reset their password, but couldn’t login. It took me the better part of a day 🙈 to figure out why some users were having problems and others weren’t.
TypeScript would have caught this IMMEDIATELY. It would have turned red in my code editor before I even tested it in the browser.
TypeScript has saved my bacon enough times to turn me into a die hard fan — to the point, where I don’t want to work on a JavaScript project without out.
I learned TypeScript in 2021. It particularly sticks out in my mind because James Q Quick and I recorded an episode of Compressed.fm where I talked about learning TypeScript (Episode 32).

As soon as I learned TypeScript, I migrated the Compressed.fm site over to TypeScript. Almost immediately, it caught a bug in the custom audio player!
If you’re still trying to decide. Let me share some cold hard facts. Every year, TypeScript continues to gain popularity. (Taken from the State of Developer Ecosystem Report.)

Also worth noting, in the same report, JavaScript is the most used programming language.

So, what are the benefits? If you’re going to invest time and energy to learn something new, what do you gain in return?
If this sounds convincing enough and you’re interested in migrating a project, it’s really a whole lot easier than you might think. When you add TypeScript to your project, you’ll have a tsconfig.json file. Inside, there’s a property for setting how “strict” TypeScript should be:
{
"strict": true,
}
Setting strict to true turns “on” all the checks. Of course, you can fine tune these to your heart’s desire. Documentation: https://www.typescriptlang.org/tsconfig/#strict
When I was first learning, I turned strict to true and would then let the error messages guide me. Heck, I still let them guide me.
Within TypeScript you can have implicit and explicit types. Implicit means they’re implied. For example:
const myName = 'Amy';
TypeScript will assume that myName is a string because Amy is wrapped in quotes. And strings are wrapped in quotes. You can still be explicit and say “THIS IS A STRING” or you can let TypeScript figure it out. TypeScript will always tell you when it doesn’t know.
I use implied types as much as possible. (1) It’s less markup and (2) if something does change TypeScript can still figure it out. And if it catches an inconsistency, it will tell you.
If you’re migrating an existing project over to TypeScript, you don’t have to turn every.single.file. into a TypeScript file. JavaScript and TypeScript files can coexist. And converting an existing JavaScript file into a TypeScript file can be as simple as changing the extension from .js to .ts.
Over the years, I’ve come to recognize that there are two different levels of TypeScript:
You can get 80% of the way with 20% of knowledge. Let me explain.
TypeScript is incredibly powerful. You can write some pretty crazy code that can pick up on what you’re trying to do and it will adjust it’s expectations accordingly. — If you pass a string into a function, return a string. Or, if they pass a number into that same function, then we need to return a number. TypeScipt can handle both conditions.
As a framework developer or a library maintainer you have to take these different use cases into account. But, if you’re just building your own project, everything is more straightforward. I say that to encourage you. If you’ve seen TypeScript code that looks like gobbly gook and ran away screaming, “Never ever will I ever.” Your TypeScript code for Everyone Else(TM) doesn’t have to be that complicated.
There are a handful of TypeScript primitives that you need to know.
int vs float )I told you, literally a handful! ✋ Chances are, you’re already mentally assigning types to your variables anyway!
In the example, above, I can say that myName is a string, by saying:
const myName: string = "Amy";
🍋 Easy, right? Or
let isAmazing: boolean;
Here, we said that isAmazing will be a true or false value. (Of course, it’s true) But, if tried to assign it a value of "maybe" it would return an error.
If you have an array, you can simply add specify the type of the array and then add square brackets. For example:
const myName: string[] = ['Amy', 'Dutton'];
Or, another example:
const kidsAges: number[] = [7, 9, 10];
A value of "teenager" would return an error (and a problem … just kidding 😁). But, again, if there is an error, it will tell you immediately.
An object is similar, but instead of square brackets, you can use curly brackets.
const person: {} = {
firstName: "Amy",
lastName: "Dutton",
isAwesome: true
}
Objects are more complex in that you can have mixed types within an object. You can be explicit about the types within the object.
const person: {
firstName: string,
lastName: string,
isAwesome: boolean
} = {
firstName: "Amy",
lastName: "Dutton",
isAwesome: true
};
If that syntax feels a little dirty, you can abstract it:
interface PersonType = {
firstName: string,
lastName: string,
isAwesome: boolean
}
const person: PersonType {
firstName: "Amy",
lastName: "Dutton",
isAwesome: true
};
One benefit to listing it out separately, is now you can export PersonType and use it within another file. This helps keep data consistent across multiple files!
A sixth type is a function. (This destroys my “handful” 🖐️ of types, unless of course we’re talking about the 6th finger man)

Let’s create a function called isPodcasting. I can specify that it’s a function by using an empty arrow function () => {}
interface PersonType {
firstName: string,
lastName: string,
isAwesome: boolean,
isPodcasting: () => {}
}
const person: PersonType = {
firstName: "Amy",
lastName: "Dutton",
isAwesome: true,
isPodcasting: (dayOfWeek) => {
if (dayOfWeek === "Wednesday") return true;
return false;
}
};
Just like objects can have multiple types, functions can have different types. You can pass in a string or a number or a boolean and get back something completely different. We can explicitly define that too:
interface PersonType {
firstName: string,
lastName: string,
isAwesome: boolean,
isPodcasting: (dayOfWeek: string) => boolean
}
const person: PersonType = {
firstName: "Amy",
lastName: "Dutton",
isAwesome: true,
isPodcasting: (dayOfWeek) => {
if (dayOfWeek === "Wednesday") return true;
return false;
}
};
Hey-O! You’re a TypeScript developer now!
If you want to go a little bit deeper, I did a session for Women Who Code. Even though this was two years, all the content is still current and relevant.
https://www.youtube.com/watch?v=GTYEgd3Q7xw
Next week, we’ll take a look at:
I would still love your feedback on this newsletter. I’m still trying to settle into a format and I want to ensure that it’s moving in the right direction.
When I was a newly wed, I told my husband, “If you don’t like something I cook, you better tell me now, otherwise you’re going to eating it the rest of your life.” — The same concept applies here. Speak now or forever hold your peace. 😂
Feel free to reply directly to this email or fill out the feedback form ABC style:
Until next time, keep coding,
Amy