DEV Community

loading...
Cover image for Unifying our basics of TypeScript

Unifying our basics of TypeScript

jamesfthomas profile image James F. Thomas Updated on ・5 min read

Exploring the "Union Type" and how it is applied.

Introduction:

Last week we ended our journey into the basics of TypeScript (TS) by showcasing how the language implements the features of static typing, optional inferred typing, and how it utilizes the static typing rules with complex data types called interfaces. Remember static typing refers to the dev being required to define the variable data types before use, optional inferred typing is when the compiler sets variables data type from the first value assigned to it, and finally, interfaces are the construction blueprints that outline the member or return types of the values encapsulated within our complex data structures (objects, arrays, functions). These rules were all employed with variables that were assigned to a single value or output type. This week it is my goal to highlight how the TS language utilizes another characteristic in order to combine these usually singular assignments into a variety of inputs and outputs for the variables a developer may need to utilize in the code their composing. Let us jump right in and see how TS unites the selections we have available to make our code more accepting of all the possibilities.

What is the Union Type?

The union type is an attribute of the TS language that allows a developer to choose from many possible value data types for their variable assignments, function inputs, and returns. Up until this point in my coding journey, I have personally been exposed to single value assignments. The closest situation in which I have gotten to experience something similar to the union type in JavaScript (JS) is using conditional statements to evaluate for data type and then controlling the response based on those data types encountered.

JS code example:


let exampleFunction = (input) => {
  if (typeof input === "string"){
    console.log("value is a string"); 
  }
  else if (typeof input === "number"){
    console.log("value is a number"); 
  };
    console.log("input must be number or string");
};

exampleFunction(true); 

// prints "input must be number or string"

Enter fullscreen mode Exit fullscreen mode

The above code block is an example of how I have previously utilized aspects of JS to evaluate variable data types and then control program response based solely on the data type entered as an argument to the function. The if conditional coupled with the typeof operator work well to accomplish this goal, but as you can see there are multiple steps that need to be put into place in order to accomplish this goal.

With each piece of the block that needs to be set in place, there is another chance for error and so enters the TS Union type to make the life of a new dev like me a little bit simpler. With TS the task of assigning expected specific variable data types is accomplished by using the Union type, and the single “|” pipe operator.

TS code example:

let fixCar = function(cartype: "MITSUBISHI" | "TOYOTA"){
    if (cartype === "MITSUBISHI" || "TOYOTA"){
        return "your vehicle is fixed";
    }
    return "We don't service that make of vehicle here."
}

console.log(fixCar("FORD"))

// Argument of type '"FORD"' is not assignable to parameter of type '"MITSUBISHI" | "TOYOTA"'.


Enter fullscreen mode Exit fullscreen mode

Looking at the above TS example we can easily see how the code block is far simpler than the JS code which performs the same task. We have fewer if conditionals to evaluate the parameter ‘cartype’, and we no longer need to utilize the typeof operator. To me, the beauty of this union type comes about when you attempt to use the function fixCar(). Remember “Static Typing”, well here it is again, by utilizing the union type when we define the function parameters we will receive an immediate error message from the compiler when we attempt to use the function fixCar() with any other parameters besides those explicitly defined in the function declaration.

What else can I unite in TS?

Now that we have seen one example use of the Union type in TS, let's quickly look at a few other examples of how we can use the Union type to require certain inputs for our data structures.

simple data type example:

let singleVar: string | boolean;

singleVar = "I'm OK"; // Good

singleVar = true; // Good

singleVar = 24; // Bad => Type '24' is not assignable to type 'string | boolean'.(2322)

Enter fullscreen mode Exit fullscreen mode

In the above code block, we have utilized the Union type to explicitly require that and value assigned to the singleVar variable be of the “string” or “Boolean” type. Any other value types will cause the compiler to throw an error and our code won’t run.

mixed data type example:

let mixedVar: string | string[];

mixedVar = 'This is good'

mixedVar = ["I'm good too"] 

mixedVar = true; // Bad => Type 'boolean' is not assignable to type 'string | string[]'.

mixedVar = [24, 'Not Good', true];
 // Type 'number' is not assignable to type 'string'.
 // Type 'boolean' is not assignable to type 'string'

Enter fullscreen mode Exit fullscreen mode

In the above code block, we have utilized the union type to explicitly require that the value assigned to the “mixedVar” variable be a “string” or an array of “string” types variables. I really thought this was a cool use when I first encountered it. Not only will TS type check your single values, it will do the same to values inside your complex data types. Now honestly how cool is that?

complex data type example:

interface Student {
    name: string;
    age: number;
};

interface School {
    programName: string;
};

type CodingStudent = Student | School;

let coder: CodingStudent = {
    name: "James",
    age: 36
};

coder = true; //Type 'boolean' is not assignable to type 'CodingStudent'.

coder = {
    programName: "Operation Spark" 
}


Enter fullscreen mode Exit fullscreen mode

In our final code example above, we have utilized not only the Union type but we have also created a custom type by combining the requirements defined in our interfaces. Combining interfaces allowed us to create instances that can contain attributes from either interface and still satisfy our static typing restrictions set within either interface.

Conclusion:

In this leg of or journey, we expanded our understanding of the static typing system employed in the TS language by combining it with the Union type. The Union type allows us to increase the choices of possible values that can be assigned to the variables I want to use in my code. The Union type can be combined with simple or complex data values, along with other aspects of the TS language to create custom types via the | & type operators. I am really enjoying learning about the new ways that TS is providing me to interact with my code and will continue to explore them in blogs to come. I'm looking forward to unpacking the concept of type guarding in the very near future, but first, more research and practice so it's presented in a clear and correct way. Hope you learned a little something new.

Happy Coding!!!

Alt Text

Sources:

Discussion

pic
Editor guide