On Typescript
typescript
A few notes on Typescript for my future self.
First Principles
- Let your types be flexible
- Let your constraints be rigid
TL;DR Rules
- Use
unknowninstead ofany, then use type narrowing to get the correct type. - Use
typeoverinterface, unless you actually need to reach for an interface or need to express objects/class inheritance. - Avoid using
asto assert types, most of the time you actually want to narrow the type with checks (if/else). - Use
array.at(index)instead ofarray[index]unless array is a tuple (fixed size array). - NEVER use TS specifics (
enum,privatein constructor, etc.).
Recommandations
- Use
satisfiesto check if an object fits a type but not erase the type. - Use
as constwhenever possible. (Immutable data, enum-like objects, etc.) - Define (and export) types where they are consumed, and import them from other files if needed.
Explanations
Narrowing over using as
Suppose you have a function that takes a number
function double(a: number) {
return a * 2;
}And you have a variable that could be a number or a string
function getNumberOrString(): number | string {
return Math.random() > 0.5 ? 1 : "1";
}
const a: number | string = getNumberOrString();Typescript will allow you to use as to assert the variable to a number (this is one of the ways that TypeScript is not sound)
const result: number = double(a as number);But this not correct/sound at runtime!
The correct way to do this is to narrow the type with a check (if/else/early return).
if (typeof a === "number") {
const result = double(a);
}