As per TypeScript Literal Types, we can refer to specific strings and numbers in type positions. So the below is valid.
function printText(s: string, alignment: "left" | "right") {
// ...
}
printText("Hello, world", "left"); // This works
printText("G'day, mate", "centre"); // This gives error - Argument of type '"centre"' is not assignable to parameter of type '"left" | "right"'.
However, this does not apply when a variable is initialized with an object because TypeScript assumes that the properties of that object might change values later. The workaround to this is to add a type assertion (in either of the locations - change 1 and change 2).
For e.g.
// Change 1:
const req = { url: "https://example.com", method: "GET" as "GET" };
// Change 2
handleRequest(req.url, req.method as "GET");
The above will work. But if I try to insert some different strings in method property, those will also be considered valid. Although not if I add a number. For e.g.
function handleRequest(url: string, method: "GET"|"POST"):void{
console.log(method);
}
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method as "POST"); // This is accepted and works
const req1 = { url: "https://example.com", method: "ABCD" };
handleRequest(req1.url, req1.method as "GET"); // This is accepted and works
const req2 = { url: "https://example.com", method: 2 };
handleRequest(req2.url, req2.method as "GET"); // This throws an error - Conversion of type 'number' to type '"GET"' may be a mistake because neither type sufficiently overlaps with the other.
TypeScript is able to properly compile when comparing to numbers but not when other strings are involved ?