In TypeScript, literal types allow you to use specific literal values as types. This feature is particularly useful when you want to enforce that a variable can only have one of a set of predefined values. Literal types are a subset of more general types like string, number, or boolean and provide a way to be even more precise about the values your variables can hold.
Literal types in TypeScript refer to types that represent exact literal values, such as strings, numbers, booleans, etc. When you use a literal type, you are specifying that a variable must have exactly that value, nothing else. This is different from using the broader type (like string), which allows any string value.
For example, if you declare a variable with a literal type of "hello", it can only hold the exact value "hello" and no other strings.
String literal types are used to restrict a variable to one or more specific string values. Here’s how you can use them:
1let direction: "north" | "south" | "east" | "west";23direction = "north"; // Valid4// direction = "up"; // Error: Type '"up"' is not assignable to type '"north" | "south" | "east" | "west"'
In this example, the direction variable can only be assigned one of the four specified string literals.
Similarly, you can use number literal types to restrict a variable to specific numeric values:
1let statusCode: 200 | 404 | 500;23statusCode = 200; // Valid4// statusCode = 301; // Error: Type '301' is not assignable to type '200 | 404 | 500'
Boolean literal types can be used to restrict a variable to only true or false, though this is less common since the boolean type already covers both values.
1let isValid: true | false;23isValid = true; // Valid4// isValid = null; // Error: Type 'null' is not assignable to type 'true | false'
Literal types can be combined with union types to create a behavior similar to enums, but without the overhead of defining an enum:
1type Suit = "hearts" | "diamonds" | "clubs" | "spades";23function describeCard(suit: Suit) {4return `The card is from the ${suit} suit.`;5}67console.log(describeCard("hearts")); // Valid8// console.log(describeCard("joker")); // Error: Argument of type '"joker"' is not assignable to parameter of type 'Suit'
In this example, the describeCard function expects a value that matches one of the literal types defined in the Suit union.
Literal types can also be used within functions to enforce specific return values:
1function getAnswer(question: "the meaning of life"): 42 {2if (question === "the meaning of life") {3return 42;4}5// Error: This condition will always return 'false' since the types '"the meaning of life"' and '"universe"' have no overlap.6else if (question === "universe") {7return 108; // Type '108' is not assignable to type '42'8}9throw new Error("Unknown question");10}1112console.log(getAnswer("the meaning of life")); // Valid13// console.log(getAnswer("what is love?")); // Error: Argument of type '"what is love?"' is not assignable to parameter of type '"the meaning of life"'
Here, the getAnswer function is restricted to only accept a specific string literal and return a specific number.
In the next section, we will explore Type Assertions. Type assertions allow you to tell the TypeScript compiler that you know more about a value than it can infer on its own. This can be useful when dealing with complex types or third-party libraries where type information might not be available.
Stay tuned for more advanced TypeScript topics and keep refining your skills!