Code TypeScript gần chục năm, qua .NET thấy cũng lạ lạ

Phong

Chào mấy bạn, lâu quá hông gặp ha.

Hôm nay rảnh, mình ngồi viết vài dòng tản mạn về chuyện code xịn — à không, về chuyện TypeScript với .NET á. Mấy bữa nay mình cứ loanh quanh với hai thằng này, tự nhiên thấy cũng có nhiều chuyện để kể.

Thiệt tình là mình mần JavaScript với TypeScript cũng gần chục năm rồi. Hồi đó mới bắt đầu, mình cũng chỉ biết jQuery với mấy dòng JavaScript lèo tèo. Rồi dần dần, từ AngularJS (nhớ cái thời đó hông?), qua React, rồi Vue, rồi lại React — mà thôi, để hôm khác kể chuyện đó dài lắm.

Cái mình muốn nói hôm nay là: Code TypeScript lâu rồi, qua .NET thấy cũng quen mà cũng... lạ.

Code trên màn hình Ảnh: Al Nahian — Pexels

Quen ở chỗ nào

Cả hai đều là static typing. TypeScript có interface, C# cũng có interface. TypeScript có generics, C# cũng có generics. Nói chung nếu bạn quen suy nghĩ theo kiểu "cục này nó là kiểu gì, trả về cái gì" thì cả hai đều dễ.

Có lần mình viết API bằng C#, tự nhiên quen tay gõ:

interface User {
  id: number;
  name: string;
}

Thay vì:

public record User(int Id, string Name);

Cũng na ná nhau ha? 🙃

Lạ ở chỗ nào

C# nó nghiêm khắc hơn nhiều. TypeScript kiểu "ờ cũng được, mày muốn làm gì thì làm, nhưng tao cảnh cáo nha". Còn C# nó kiểu "mày muốn làm cái này? Chứng minh đi, không thì cút".

Ví dụ dễ thấy nhất: nullable. TypeScript với strictNullChecks bật lên thì nó cũng nhắc "ê cái này có thể undefined đó". Nhưng bạn vẫn optional chaining ?. hoặc ép kiểu as để bypass được. Còn C# với NRT (nullable reference types) thì khó chịu hơn — đặc biệt với mấy cha DI container, constructor injection, nếu khai báo hông đúng là nó bắt lỗi compile liền.

Hồi đầu mình cũng hơi bực, nhưng lâu dần thấy hay. Cái khó chịu đó làm bug null reference gần như biến mất.

Laptop và cà phê Ảnh: Pixabay — Pexels

Cái mình thích nhất ở mỗi thằng

TypeScript — dân chơi hệ linh hoạt

Phải nói là TypeScript có cái type system cực kỳ linh hoạt. Union types, intersection types, discriminated unions — mấy cái này C# hông có (hoặc có mà hông đẹp bằng).

Ví dụ:

type Result<T> = 
  | { status: 'success'; data: T }
  | { status: 'error'; message: string };

Kiểu này xài với switch-case discriminated union thì ngon vãi. Muốn thêm cái loading state? Chỉ cần thêm một dòng:

  | { status: 'loading' };

Xong. Không cần sửa code xử lý ở mấy chỗ khác. Được cái compiler nó bắt mình xử lý hết tất cả cases.

Cùng lắm thì C# phải dùng OneOf library, hoặc pattern matching với record. Cũng được nhưng hông gọn bằng.

.NET — dân chơi hệ architecture

Ngược lại, .NET có mấy thứ TypeScript chỉ có mơ. Dependency Injection built-in, Middleware pipeline, attribute decoration đủ kiểu. Lúc mới qua .NET mình thấy mấy cái này tiện hơn xài Express hay NestJS.

Đặc biệt là Entity Framework. Mình từng vật lộn với TypeORM, Prisma — cũng ngon, nhưng EF Core già dặn hơn, ít bug hơn. Nó có learning curve riêng, nhưng một khi đã hiểu thì code nhanh dữ lắm.

À còn cái nữa: .NET Aspire. Mới ra mà mê vãi. Orchestrate mấy service chạy distributed, nhìn cái dashboard thấy đã. TypeScript bên kia cũng có những thứ tương tự nhưng hông mượt bằng.

Tổng kết

Mỗi thằng có điểm mạnh riêng. Mình thấy may mắn vì được làm cả hai — nó bổ sung cho nhau. TypeScript dạy mình về type flexibility và design patterns linh hoạt, .NET dạy mình về architecture chắc chắn và kỷ luật hơn.

Có bạn nào cũng làm cả hai giống mình hông? TypeScript với .NET — bạn thích cái gì nhất ở mỗi thằng? Vô cmt kể cho mình nghe với nha!

Hẹn gặp lại mấy bạn bài sau. Mình đi pha ly cà phê muối đây ☕