TypeScript 一日速通指南:数据类型全解析与转换指南

TypeScript 数据类型全解析与转换指南


一、核心数据类型体系
1. 基础类型(Primitive Types)
类型 描述 示例 特殊说明
number 数值类型(含整数、浮点数、科学计数法) let age: number = 25; 支持二进制(0b)、八进制(0o)、十六进制(0x)字面量
string 字符串类型 const str: string = "TypeScript"; 支持模板字符串(Hello ${name}
boolean 布尔值 let flag: boolean = true; true/false 两个值
symbol 唯一标识符 const sym: symbol = Symbol(); 用于对象属性的唯一键
bigint 任意精度整数 const big: bigint = 123n; 需添加 ESNexttsconfig.lib
2. 复合类型(Compound Types)
类型 描述 示例
Array<T> / T[] 数组类型 const arr: number[] = ;
Tuple 固定长度和类型的数组 let tuple: @ref;
enum 枚举类型(数字/字符串枚举) enum Color { Red, Green }
object 非原始类型(排除 number/string/boolean 等) const obj: object = { a: 1 };
any 任意类型(慎用) let data: any = apiResponse;
unknown 安全的未知类型(需类型守卫) let input: unknown = getInput();
3. 特殊类型
类型 描述 示例
void 无返回值函数 function log(): void {}
never 永不存在值的类型(抛出异常/死循环) function error(): never {}
literal 字面量类型(精确匹配特定值) `type Status = "success"

二、类型转换全攻略
1. 显式类型转换
1.1 类型断言(Type Assertion)
typescript 复制代码
// 尖括号语法
const str: unknown = "123";
const num: number = (<string>str).length;

// as 语法(推荐)
const arr: any@ref;
const filtered = arr.filter((item): item is number => typeof item === "number");
1.2 函数转换
typescript 复制代码
// 字符串转数字
const numStr: string = "123.45";
const num: number = Number(numStr);       // 123.45
const int: number = parseInt(numStr, 10); // 123

// 数字转字符串
const num: number = 42;
const str1: string = String(num);         // "42"
const str2: string = num.toString();      // "42"
2. 隐式类型转换
2.1 运算符驱动
typescript 复制代码
// 字符串拼接
const result = 5 + "px"; // "5px"(数字隐式转字符串)

// 逻辑运算
const isAdmin = true;
const isAdminStr = isAdmin + ""; // "true"(布尔值转字符串)

// 算术运算
const value = "10" - 5;    // 5(字符串转数字)
const isTruthy = !!value;  // true(数字转布尔)
2.2 类型收窄(Type Narrowing)
typescript 复制代码
function printLength(value: unknown) {
  if (typeof value === "string") {
    console.log(value.length); // 类型收窄为 string
  } else if (Array.isArray(value)) {
    console.log(value.length); // 类型收窄为 any[]
  }
}

三、避坑指南与最佳实践
1. 类型转换常见陷阱
问题类型 示例 修复方案
隐式转换导致的精度丢失 const a: number = 0.1 + 0.2; 使用 toFixed() 控制精度
any 类型滥用 let data: any = apiResponse; 改用泛型 + 类型守卫
null/undefined 处理 const len = str.length; 添加非空断言 str!.length 或默认值
枚举反向映射失效 enum Color { Red = 1 } 使用 Color 时需确保唯一性
2. 安全转换模式
typescript 复制代码
// 安全解析 JSON
const parseJSON = <T>(json: string): T => {
  try {
    return JSON.parse(json);
  } catch {
    throw new Error("Invalid JSON");
  }
};

// 类型守卫组合
const isUser = (obj: unknown): obj is User => {
  return (
    typeof obj === "object" &&
    "id" in obj &&
    typeof (obj as User).id === "string"
  );
};
3. 性能优化技巧
typescript 复制代码
// 避免重复类型断言
const process = (data: unknown) => {
  const str = data as string; // 单次断言
  return str.toUpperCase();
};

// 使用类型谓词减少重复检查
type Primitive = string | number | boolean;
const isPrimitive = (val: unknown): val is Primitive => {
  return val === null || typeof val !== "object";
};

四、进阶类型转换
1. 高级类型操作
typescript 复制代码
// 映射类型转换
type ReadonlyUser = Readonly<User>;

// 条件类型过滤
type FilterString<T> = T extends string ? T : never;

// 模板字面量类型
type Event = "click" | "hover";
type Handler = `${Event}Handler`;
2. 运行时类型校验
typescript 复制代码
// Zod 校验库示例
import { z } from "zod";

const UserSchema = z.object({
  id: z.string().uuid(),
  age: z.number().int().positive(),
});

const parseUser = (input: unknown) => {
  return UserSchema.parse(input);
};

五、实战建议
  1. 类型优先原则 :优先使用 unknown 而非 any,通过类型守卫逐步缩小范围

  2. 严格模式配置

    json 复制代码
    // tsconfig.json
    {
      "compilerOptions": {
        "strictNullChecks": true,
        "noImplicitAny": true,
        "strictFunctionTypes": true
      }
    }
  3. 类型文档化 :为复杂类型添加 JSDoc 注释

    typescript 复制代码
    /**
     * @typedef {Object} User
     * @property {string} id - 用户唯一标识
     * @property {"admin"|"user"} role - 用户角色
     */

通过掌握类型系统的核心机制和转换技巧,开发者可以显著提升代码健壮性。建议结合具体业务场景,灵活运用类型断言、类型守卫和高级类型工具,构建类型安全的代码体系。


React/Vue/Angular项目中,类型转换有哪些特殊注意点

在 React/Vue/Angular 项目中使用 TypeScript 时,类型转换需特别注意框架特性与类型系统的交互。以下是各框架的核心注意事项及通用最佳实践:


一、React 项目注意事项

1. 组件 Props 类型安全
  • 问题 :直接传递 any 类型或未定义 Props 会导致运行时错误

  • 解决方案

    tsx 复制代码
    // 使用泛型精确约束
    interface User { id: string; name: string }
    const UserProfile = ({ user }: { user: User }) => { /* ... */ }
    
    // 使用 TypeScript 的泛型约束
    const fetchUser = <T extends { id: string }>(id: T["id"]): Promise<T> => { /* ... */ }
2. 事件处理类型
  • 问题:未正确标注事件对象类型会导致属性访问错误

  • 解决方案

    tsx 复制代码
    const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
      e.preventDefault(); // 自动提示 preventDefault 方法
    }
3. 状态管理类型
  • 问题:useReducer/useContext 的泛型缺失导致类型推断错误

  • 解决方案

    tsx 复制代码
    type State = { count: number };
    const [state, dispatch] = useReducer(reducer, initialState as State);

二、Vue 项目注意事项

1. 响应式类型推导
  • 问题:reactive/ref 的初始值类型推断不准确

  • 解决方案

    ts 复制代码
    // 显式标注类型
    const count = ref<number>(0);
    const user = reactive<{ name: string }>({ name: "John" });
2. 组件 Props 与 Emits
  • 问题:未使用 defineProps/defineEmits 导致类型丢失

  • 解决方案

    ts 复制代码
    // script setup 语法
    const props = defineProps<{
      list: Array<{ id: number }>;
    }>();
    
    const emit = defineEmits<{
      (e: "update", value: string): void;
    }>();
3. 解构响应式对象
  • 问题:解构导致响应性丢失

  • 解决方案

    ts 复制代码
    // 正确方式
    const { foo } = toRefs(state);
    // 错误方式(失去响应性)
    const { foo } = state;

三、Angular 项目注意事项

1. 依赖注入类型
  • 问题:未标注服务类型导致注入错误

  • 解决方案

    ts 复制代码
    @Injectable({ providedIn: 'root' })
    class DataService {
      getData(): Observable<Data[]> {
        return of([] as Data[]);
      }
    }
2. RxJS 类型操作
  • 问题:未正确标注 Observable 类型

  • 解决方案

    ts 复制代码
    getData(): Observable<{ id: string }[]> {
      return this.http.get<{ id: string }[]>('/api/data');
    }
3. 模板类型检查
  • 问题:模板中访问未定义的属性

  • 解决方案

    html 复制代码
    <!-- 使用安全导航操作符 -->
    <div *ngIf="user?.address?.city"></div>

四、跨框架通用最佳实践

1. 类型断言陷阱
  • 问题 :滥用 as 导致运行时错误

    tsx 复制代码
    // 错误示例
    const data = localStorage.getItem("key") as string; // 可能为 null
  • 解决方案

    ts 复制代码
    const data = localStorage.getItem("key");
    if (typeof data === "string") {
      // 安全操作
    }
2. 第三方库类型处理
  • 问题:缺乏类型定义导致类型错误

  • 解决方案

    ts 复制代码
    // 声明文件补充
    declare module "legacy-lib" {
      export function getData(): Promise<{ id: string }[]>;
    }
3. 异步数据类型
  • 问题:未处理 Promise 的泛型类型

  • 解决方案

    ts 复制代码
    const fetchData = async (): Promise<User[]> => {
      const res = await fetch("/api/users");
      return res.json() as Promise<User[]>; // 需要运行时验证
    }
4. 类型守卫实践
  • 问题:未正确缩小联合类型范围

  • 解决方案

    ts 复制代码
    function isUser(obj: unknown): obj is User {
      return "id" in obj && typeof obj.id === "string";
    }

五、框架对比与特殊场景

场景 React Vue Angular
DOM 操作类型 使用 ref + 类型断言 使用 ref 显式标注 使用 @ViewChild 类型参数
状态管理 Redux Toolkit 的 createSlice 泛型 Pinia 的 defineStore 类型推导 NgRx 的 Action 类型标注
表单处理 Formik 的 FieldProps 泛型 Element Plus 的 defineComponent ReactiveFormsModule 类型检查
路由参数类型 React Router 的 useParams 泛型 Vue Router 的 defineRoute Angular Router 的路由守卫类型

六、调试与验证工具

  1. 类型校验库

    ts 复制代码
    import { z } from "zod";
    const schema = z.object({ id: z.string().uuid() });
    const data = schema.parse(apiResponse); // 运行时验证
  2. 类型可视化

    ts 复制代码
    // 查看类型定义
    type Props = typeof component.props;
  3. 严格模式配置

    json 复制代码
    // tsconfig.json
    {
      "compilerOptions": {
        "strictNullChecks": true,
        "noUncheckedIndexedAccess": true
      }
    }

通过遵循框架特性和类型系统规则,开发者可以在 React/Vue/Angular 项目中充分发挥 TypeScript 的优势,同时规避类型相关的潜在风险。建议结合具体业务场景,建立统一的类型规范和代码检查流程。


相关推荐
叫我一声阿雷吧2 小时前
【JS 实战案例】用 JS 实现页面滚动到指定位置(带动画)
javascript·页面交互·js实战案例·平滑滚动·前端零基础·锚点导航
We་ct2 小时前
React 更新触发原理详解
开发语言·前端·javascript·react.js·面试·前端框架·react
还是大剑师兰特2 小时前
Vue3 页面权限控制实战示例(路由守卫 + 权限判断)
开发语言·前端·javascript
跟着珅聪学java3 小时前
Vue 2 + CommonJS 写法开发教程
前端·javascript·vue.js
qq_246100053 小时前
CSDN risk probe 1773588273
开发语言·javascript·ecmascript
ByteCraze3 小时前
Vue 递归组件实战:手写一个文件/文件夹树形组件
javascript·vue.js·ecmascript
前端Hardy3 小时前
前端如何防止用户重复提交表单?4 种可靠方案(附防坑指南)
前端·javascript·面试
前端Hardy3 小时前
用户真的关掉页面了吗?前端精准检测页面卸载的 4 种方法(附避坑指南)
前端·javascript·面试