const typesOfBeetles = ["insects", "musicians"];
typesOfBeetles.push("cars"); // okconst typesOfBeetles = ["insects", "musicians"] as const;
// Property 'push' does not exist on type 'readonly ["insects", "musicians"]'.ts(2339)
typesOfBeetles.push("cars");Without as const:
![screenshot of vscode, hovering over code. Type shown is string[]](/images/hints/as-const/without-as-const.png)
With as const:
![screenshot of vscode, hovering over code. Type shown is readonly ["insects", "musicians"]](/images/hints/as-const/with-as-const.png)
Take this code:
const directions = ["north", "south", "east", "west"];
function move(direction: string) {
console.log(`You moved ${direction}`);
}The move function takes one argument: direction. direction has type string right now, but really, its only options should be the values in the directions array. How can we make that happen?
This doesn't work:
const directions = ["north", "south", "east", "west"];
type Direction = typeof directions; // string[]We could use an indexed access type:
const directions = ["north", "south", "east", "west"];
type Direction = (typeof directions)[number]; // stringThis gives us the type of the elements in the array instead of the type of the array itself. But this still doesn't work because TypeScript is inferring the type as string. The problem is, we could mutate the array:
const directions = ["north", "south", "east", "west"];
directions.push("blah");So TypeScript has to go with a broad type that accommodates us adding to the array. But if we use as const:
const directions = ["north", "south", "east", "west"] as const;
directions.push("blah"); // error!Now TypeScript will know that the array is immutable. Now, using typeof gives us a more specific type:
type Direction = (typeof directions)[number]; // "north" | "south" | "east" | "west"Perfect! Now we can use it:
const directions = ["north", "south", "east", "west"] as const;
type Direction = (typeof directions)[number];
function move(direction: Direction) {
console.log(`You moved ${direction}`);
}
move("north");
// Argument of type '"blah"' is not assignable to parameter of type '"north" | "south" | "east" | "west"'.ts(2345)
move("blah");