前端TypeScript高级技巧:让你的代码更安全

前端TypeScript高级技巧:让你的代码更安全

毒舌时刻

前端TypeScript?这不是增加工作量吗?

"JavaScript就够了,为什么要用TypeScript"------结果类型错误频发,调试困难,

"TypeScript太严格了,我写起来很麻烦"------结果代码质量差,维护困难,

"我只在关键地方用TypeScript,其他地方用any"------结果失去了TypeScript的意义。

醒醒吧,TypeScript不是负担,而是提高代码质量的利器!

为什么你需要这个?

  • 类型安全:在编译时发现类型错误
  • 代码提示:提供更好的IDE智能提示
  • 重构安全:重构代码时更加安全
  • 可读性:代码更加清晰易懂
  • 可维护性:减少运行时错误,提高代码可维护性

反面教材

typescript 复制代码
// 反面教材:过度使用any
function processData(data: any) {
  // 没有类型检查,容易出错
  return data.name.toUpperCase();
}

// 反面教材:类型定义不完整
interface User {
  id: number;
  name: string;
  // 缺少email等其他属性
}

// 反面教材:类型断言滥用
function getUser(id: number): User {
  // 不安全的类型断言
  return fetch(`/api/users/${id}`).then(res => res.json()) as unknown as User;
}

正确的做法

typescript 复制代码
// 正确的做法:使用泛型
function identity<T>(arg: T): T {
  return arg;
}

// 使用泛型约束
interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

// 正确的做法:使用联合类型和类型守卫
type Shape = Circle | Square;

interface Circle {
  kind: 'circle';
  radius: number;
}

interface Square {
  kind: 'square';
  sideLength: number;
}

function getArea(shape: Shape): number {
  // 类型守卫
  if (shape.kind === 'circle') {
    return Math.PI * shape.radius ** 2;
  } else {
    return shape.sideLength ** 2;
  }
}

// 正确的做法:使用类型推断
const user = {
  id: 1,
  name: '张三',
  email: 'zhangsan@example.com'
};

// TypeScript会自动推断user的类型

// 正确的做法:使用映射类型
interface Person {
  name: string;
  age: number;
}

// 生成只读类型
type ReadonlyPerson = Readonly<Person>;

// 生成可选类型
type PartialPerson = Partial<Person>;

// 生成必填类型
type RequiredPerson = Required<PartialPerson>;

// 正确的做法:使用条件类型
// 提取Promise的返回类型
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

// 测试
async function fetchData(): Promise<string> {
  return 'data';
}

// 类型会被推断为string
let data: UnwrapPromise<ReturnType<typeof fetchData>>;

// 正确的做法:使用模板字面量类型
type EventName<T extends string> = `${T}Changed`;
type MouseEventName = EventName<'click' | 'mouseover' | 'mouseout'>;
// 类型为 'clickChanged' | 'mouseoverChanged' | 'mouseoutChanged'

// 正确的做法:使用类型别名和接口
// 类型别名

type UserID = number;
type UserName = string;
type Email = string;

// 接口
interface User {
  id: UserID;
  name: UserName;
  email: Email;
  createdAt: Date;
  updatedAt: Date;
}

// 正确的做法:使用枚举
enum Role {
  Admin = 'admin',
  User = 'user',
  Guest = 'guest'
}

function checkPermission(role: Role): boolean {
  return role === Role.Admin;
}

// 正确的做法:使用命名空间
namespace Validation {
  export interface StringValidator {
    isAcceptable(s: string): boolean;
  }

  const lettersRegexp = /^[A-Za-z]+$/;
  const numberRegexp = /^[0-9]+$/;

  export class LettersOnlyValidator implements StringValidator {
    isAcceptable(s:
相关推荐
六月的可乐3 分钟前
【干货】小程序虚拟瀑布流探索小结
前端·react.js·小程序
techdashen10 分钟前
Rust 项目管理动态 — 2026 年 3 月
前端·人工智能·rust
原则猫11 小时前
HOOKS 背后机制
前端
码语智行11 小时前
首页导航跳转功能深度解析-系统内和系统外
前端
阿猫的故乡11 小时前
Vue过渡动画从入门到装X:淡入淡出、滑动、列表动画、第三方库全搞定
前端·javascript·vue.js
IManiy12 小时前
总结之Vibe Coding前端骨架
前端
JS菌12 小时前
AI Agent 沙箱双层防护体系:从权限过滤到内核隔离的完整实现
前端·人工智能·后端
Aphasia31112 小时前
从输入URL到页面展示全流程
前端·面试
我叫黑大帅12 小时前
前端如何竖屏固定视口背景
前端·javascript·面试
abcy07121313 小时前
python pandas csv异步后台清洗前端优先返回成功信息
前端·python·pandas