Typescript Basics

For years, Javscript developers have clambered for a way to apply stricter type checking to their applications. The Typescript project is just that. Typescript allows Javascript developers to create types and interfaces for their projects to catch issues at build time, avoiding the dreaded scenario of suddenly referencing undefined values at run time. Alongside this increased level of protection, Typescript encourages more thoughtful, safer development.
Why Typescript?
Broadly, Typescript allows developers to create safer systems. Practically, and in the React based Front-End world of today (2023), this will generally boil down to creating strict data structures that can be passed between functional components and the helper functions that support creating UI.
Build Time vs. Run Time
The modern Javascript/Typescript toolchain is a doozy. Developers write their apps with a large swath of wrappers (JSX, modern ES6 syntax, etc...) that will ultimately be run through some set of tooling to produce "vanilla" Javascript. However, without Typescript, we can't be sure that code will run properly until it's actually run... in the browser... by users. It's not the cleanest or safest system for shipping immaculate code.
Typescript allows developers to surface many common errors in their code at build time - before the code can be shipped to users in the browser.
Uncaught TypeError: cannot read properties of undefined...
Ah yes. We've all seen this error, and more than likely, we've seen it flood whatever client side error monitoring service we might be using.
const language = {
name: "javascript",
typed: false,
};
console.log(language.version.toString());
// The below error will happen at RUN time
// Uncaught TypeError: Cannot read properties
// of undefined (reading 'toString')
With plain old Javascript, we have no language level way to catch these errors at build time. Javascript allows us to reference values that don't exist, and keep on writing our program as if they did. We probably won't find out about a problem like this until we run the code (of course our unit tests would catch this right away, right...)
Types: Time to be strict
Let's rewrite the below example using Typescript
type Language = {
name: string;
typed: boolean;
};
const javascript: Language = {
name: "javascript",
typed: false,
};
console.log(language.version.toString());
// The below error will happen at BUILD time
// Property 'version' does not exist on type 'Language'.
What does this code mean? What is it doing?
The magic here is the type declaration we've created. We know that our program is going to be interacting with a data structure describing programming languages. With the type declaration above, we're telling Typescript that any time we create a value that is intended to be a programming language, it must have the properties of name and typed. Furthermore, we've described what primitive type each of those attributes must be.
If we tried to create a new variable with the type of Language and it didn't match these specifications, Typescript would yell at us at build time. Furthermore, if we tried to access a property on one of these variables that wasn't part of the type, we'd also get a build time error. Both of these errors would happen long before our code ever made it to an end user.