侧边栏壁纸
博主头像
我的博客站

行动起来,活在当下

  • 累计撰写 1 篇文章
  • 累计创建 2 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

TS(一)环境搭建与十二大基础类型

TS 环境搭建与基础属性

TS 环境搭建

安装环境依赖

  • 通过 npm(Node.js 包管理器)

针对npm 用户可以安装包依赖

npm i typescript -g

然后再安装tsx 运行

npm i tsx -g

测试一下

  • 在一个新的文件夹里面新建一个Basic1.ts 文件
  • 写入如下代码
const getTime: () => void = () => {
  console.log(new Date().toLocaleString());
};
getTime();

运行一下

tsx Basic1.ts
  • 结果
2022/6/15 21:17:46

TS 基础类型

十二大类型

分成3(字符串,数字,布尔),3(null,object,undefined),2(array,tuple),2(any,unkonw),1(never),1(void) 方便记忆就是33,22,11

  • 数字类型 number
  • 字符串类型 string
  • 布尔类型 boolean
  • 空类型 null
  • 对象类型 object
  • 未定义类型 undefined
  • 数组类型 array
  • 元组类型 tuple
  • 枚举类型 enum
  • 任意类型 any
  • 未知类型 unknown
  • never类型 never
  • 没有返回值类型 void

数字类型

  • 整数类型 number
  • 浮点数类型 number
  • 大整数类型 bigint
const test_number_1: number = 100;
const test_number_2: number = 100.5;
const test_number_3: bigint = 100n;

console.log(test_number_1); // 100
console.log(test_number_2); // 100.5
console.log(test_number_3); // 100n

布尔类型

const test_boolean_1: boolean = true;

console.log(test_boolean_1); // true

const test_boolean_2: boolean = false;

console.log(test_boolean_2); // false

字符串类型

const test_string_1: string = "hello world";

console.log(test_string_1); // hello world

空类型 null

const test_null_1: null = null;

console.log(test_null_1); // null

未定义类型 undefined

const test_undefined_1: undefined = undefined;

console.log(test_undefined_1); // undefined

数组类型 array

const test_array_1: number[] = [1, 2, 3, 4, 5];

console.log(test_array_1); // [1, 2, 3, 4, 5]

const test_array_2: string[] = ["hello", "world"];

console.log(test_array_2); // ["hello", "world"]

// 数组和字符串混用
const test_array_3: (number | string)[] = [100, "hello", 200, "world"];

console.log(test_array_3); // [100, "hello", 200, "world"]

对象类型 object

  • 使用
// 可以赋值对象、数组、函数等
const obj: object = {};
const arr: object = [1, 2, 3];
const fn: object = () => {};

对象类型 object 非常宽泛,只能访问对象共有的方法.比如(valueOf(),equals(),hashCode(),toString(),equals(),hashCode()).

  • 限制
const person: object = { name: "Alice", age: 25 };

// ❌ 错误:不能访问具体属性
console.log(person.name); // Property 'name' does not exist on type 'object'

// ✅ 只能访问 Object 原型上的方法
console.log(person.toString());
  • 如果是更精确的定义 我们一般使用接口来定义对象的属性和方法.
// 1. 对象字面量类型(推荐)
const person: { name: string; age: number } = { name: "Alice", age: 25 };

// 2. interface
interface Person {
  name: string;
  age: number;
}
const p: Person = { name: "Bob", age: 30 };

// 3. Record
const map: Record<string, number> = { a: 1, b: 2 };

// 4. 索引签名
const dict: { [key: string]: any } = {};
dict["name"] = "Alice";
dict["age"] = 25;
console.log(dict);
// { name: 'Alice', age: 25 }
  • object vs Object vs {}
类型 说明
object 非原始类型(推荐用于"任意对象")
Object JS 的 Object 构造函数类型,包含原始类型包装器
{} 空对象类型,几乎包含所有值(除 null / undefined )
  • 举例
// object 不接受原始类型
const x: object = "hello"; // ❌ 错误

// Object 接受原始类型(自动装箱)
const y: Object = "hello"; // ✅ 可以
  • 总结

需要 任意对象 时:用 object

需要 具体结构 时:用 interface / 类型别名 / 字面量类型

避免使用 Object 和 {} 作为类型,它们行为怪异

元组类型 tuple

  • 元组(Tuple)是固定长度、固定类型的数组。
// 定义:第一个元素是 string,第二个是 number
const user: [string, number] = ["Alice", 25];

// 访问元素(类型已知)
const name = user[0]; // string
const age = user[1]; // number

// ❌ 越界访问会报错
const x = user[2]; // Tuple type '[string, number]' of length '2' has no element at index '2'
  • 可选元素
// 第三个元素可选
const coords: [number, number, number?] = [10, 20];
// 或
const coords2: [number, number, number?] = [10, 20, 30];
  • 剩余元素
// 前两个固定,后面任意多个 string
const log: [string, string, ...string[]] = [
  "INFO",
  "module",
  "detail1",
  "detail2",
];
  • 只读元组
const point: readonly [number, number] = [10, 20];

// ❌ 不可修改
point[0] = 100; // Cannot assign to '0' because it is a read-only property
  • 具名元组
const user: [name: string, age: number] = ["Alice", 25];

// 解构时更有语义
const [name, age] = user;
  • 与数组的区别
特性 元组[string,number] 数组(string number)[]
长度 固定 可变
元素位置类型 每个位置类型固定 所有位置类型统一
越界访问 报错 允许
  • 实际使用场景
// useState 返回的就是元组
// [number, Dispatch<<SetStateAction<number>>]
const [count, setCount] = useState(0);

// 函数返回多个值
function getUser(): [string, number] {
  return ["Alice", 25];
}

// CSV 行解析
const row: [string, string, number, boolean] = ["Alice", "Engineer", 25, true];
  • 注意事项

push 不会检查类型的安全性,会破坏元组的类型约束。

// ❌ 长度不匹配
const bad: [string, number] = ["Alice"]; // 缺少元素
const bad2: [string, number] = ["Alice", 25, 1]; // 元素过多

// ⚠️ push 不会检查类型安全(设计限制)
const t: [string, number] = ["Alice", 25];
t.push("extra"); // 不报错,但破坏元组约束

枚举类型 enum

在 TypeScript 中,枚举(Enum)用于定义一组命名的常量。

  • 数字枚举
enum Direction {
  Up, // 0
  Down, // 1
  Left, // 2
  Right, // 3
}

// 使用
const dir: Direction = Direction.Up;

// 反向映射:通过值获取名称
console.log(Direction[0]); // "Up"
console.log(Direction.Up); // 0
  • 指定初始值
enum Status {
  Pending = 1,
  Processing, // 2
  Done, // 3
  Failed = 10,
  Cancelled, // 11
}
  • 字符串枚举
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
}

// 字符串枚举没有反向映射
const c: Color = Color.Red;
console.log(c); // "RED"
  • 常量枚举(推荐)

编译时完全内联,不生成对象,性能更好:

const enum Permission {
  Read = 1,
  Write = 2,
  Execute = 4,
}

// 编译后直接替换为值
const p = Permission.Read | Permission.Write; // 编译为 const p = 1 | 2
  • 异构枚举(不推荐)
enum Mixed {
  No = 0,
  Yes = "YES",
}
  • 实际应用
// 作为联合类型使用
enum HttpStatus {
  OK = 200,
  NotFound = 404,
  ServerError = 500,
}

function handle(status: HttpStatus) {
  switch (status) {
    case HttpStatus.OK:
      return "成功";
    case HttpStatus.NotFound:
      return "未找到";
    default:
      return "错误";
  }
}

// 配置选项
const enum Feature {
  DarkMode = 1,
  AutoSave = 2,
  Notification = 4,
}

let config = Feature.DarkMode | Feature.AutoSave;
  • 注意事项
// 枚举成员在编译时确定,不能是变量
const start = 1;
enum Bad {
  // A = start  // ❌ 错误:const enum 成员只能使用常量
}
// 普通 enum 可以
enum Good {
  A = start, // ✅ 可以
}

any 类型

在 TypeScript 中, any 是最宽松的类型,表示"任意类型",会关闭该变量的类型检查。

  • 基本用法
let value: any = 4;
value = "hello"; // ✅ 不报错
value = true; // ✅ 不报错
value = {}; // ✅ 不报错

// 可以访问任意属性、调用任意方法
value.foo.bar(); // ✅ 编译不报错(运行可能报错)
  • 使用场景
// 逐步迁移时,先标记为 any,后续再细化类型
function legacyFunction(data: any): any {
  return data;
}
  • 第三方库无类型定义
// 库没有 @types 声明文件
const untypedLib: any = require("some-untyped-lib");
  • 动态内容
// JSON 解析结果
const parsed: any = JSON.parse(jsonString);

// 用户输入
const userInput: any = getDynamicData();
  • 明确需要绕过类型检查
// 测试时临时绕过
const temp: any = complicatedObject;
  • 危险操作
let x: any = "hello";

// 以下全部编译通过,但运行时可能崩溃
x.toFixed(2); // ❌ 运行时错误:字符串没有 toFixed
x[999].name; // ❌ 运行时错误
x(); // ❌ 运行时错误:不是函数
new x(); // ❌ 运行时错误
  • 与unknown类型对比

unknown 是类型安全的 any

let a: any = 4;
a.toFixed(); // ✅ 编译通过(危险)

let u: unknown = 4;
u.toFixed(); // ❌ 错误:需要先类型收窄

// unknown 必须检查后才能使用
if (typeof u === "number") {
  u.toFixed(); // ✅ 安全
}
特性 any unknown
可赋值给任何类型
可访问任何属性
类型安全 ❌ 关闭检查 ✅ 必须收窄
推荐度 尽量避免 优先使用
  • 最佳实践
// ❌ 滥用 any
function bad(data: any): any {
  return data.map((x) => x.id);
}

// ✅ 尽量用具体类型或泛型
function good<T>(data: T[]): T[] {
  return data;
}

// ✅ 不得不用时,优先 unknown
function better(data: unknown): void {
  if (Array.isArray(data)) {
    // 安全使用
  }
}

// ✅ 类型断言(明确知道类型时)
function ok(data: unknown) {
  const str = data as string;
  return str.length;
}
  • 总结

any = 关闭类型检查,编译器不再帮你

能不用就不用,用 unknown 或具体类型替代

遗留代码迁移时可用,但要逐步替换

开启 strict / noImplicitAny 防止隐式扩散

unknown 类型

unknown 是 TypeScript 3.0 引入的类型,它是 any 的安全替代品

特性 any unknown
可以赋值给任何类型
任何类型可以赋值给它
可以任意访问属性/方法
使用前需要类型检查
  • 基本用法
let a: unknown = 123;
a = "hello"; // OK
a = { x: 1 }; // OK

// ❌ 不能直接使用
let b: string = a; // Error: Type 'unknown' is not assignable to type 'string'
console.log(a.x); // Error: Object is of type 'unknown'
a.toFixed(); // Error

// ✅ 必须先缩小类型
if (typeof a === "number") {
  a.toFixed(); // OK,此时 a 被收窄为 number
}

if (a instanceof Object) {
  console.log((a as any).x); // 或者用类型断言
}
  • 常用类型收窄方式
let val: unknown;

// 1. typeof
if (typeof val === "string") val.toUpperCase();

// 2. instanceof
if (val instanceof Date) val.getTime();

// 3. 自定义类型守卫
function isString(x: unknown): x is string {
  return typeof x === "string";
}

// 4. 类型断言(确定时)
(val as string).toUpperCase();
  • 实际场景
// API 返回不确定的数据
async function fetchData(): Promise<<unknown> {
  const res = await fetch("/api");
  return res.json(); // 返回 unknown 而非 any
}

// 安全处理
const data = await fetchData();
if (typeof data === "object" && data !== null && "id" in data) {
  console.log(data.id); // OK
}

never 类型

never 表示 永远不会发生的值 的类型,它是 TypeScript 的底层类型(bottom type),所有类型的子类型。 一般用于抛出异常

  • 函数永远不会返回
// 抛出异常
function throwError(msg: string): never {
  throw new Error(msg);
}

// 无限循环
function infiniteLoop(): never {
  while (true) {}
}

// 退出程序
function exit(): never {
  process.exit(1);
}
  • 穷尽性检查
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number }
  | { kind: "rectangle"; width: number; height: number };

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.side ** 2;
    case "rectangle":
      return shape.width * shape.height;
    default:
      // 如果上面漏了某个 case,这里会报错
      const _exhaustive: never = shape;
      return _exhaustive;
  }
}
  • 条件类型中的过滤
type NonNullable<T> = T extends null | undefined ? never : T;

type A = NonNullable<string | null | undefined>; // string
  • 与any/unknown的关系
类型 特性
any 顶层类型,可赋值给任何类型,也可接受任何类型
unknown 顶层类型,可接受任何类型,赋值前需检查
never 底层类型,可赋值给任何类型,但没有任何值属于它
  • 举例说明
let n: never;

// never 可赋值给任何类型
let a: string = n; // OK
let b: number = n; // OK

// 没有任何类型(包括 never 自己)能赋值给 never
n = 1; // Error
n = ((): never => {
  throw new Error();
})(); // OK
  • 空数组的初始类型
// 不指定的话默认是 never[]
const arr: never[] = [];
// 推不出具体类型,通常应显式指定
const nums: number[] = [];
  • 总结

never 主要用来表达"不可能"——函数不返回、分支不可达、类型过滤后的剩余。它在编译期帮你捕获遗漏的分支,是类型安全的重要工具。

void 类型

void 表示 没有返回值 或 返回值为 undefined ,主要用于函数。

  • 基本用法
// 函数没有 return,或 return 不带值
function log(msg: string): void {
  console.log(msg);
  // 没有 return
}

function noop(): void {
  return; // return 不带值,也是 void
}

// 变量声明为 void,只能赋 undefined 或 null(非严格模式下)
let v: void = undefined;
  • 与undefined的区别
使用 void undefined
用途 函数返回类型 值类型
含义 不care返回值 值就是undefined
函数实现 可以没有return,或return空 必须return undefined
  • 举例
// void:不关心返回什么
function f1(): void {
  console.log(1);
}

// undefined:必须返回 undefined
function f2(): undefined {
  console.log(1);
  return undefined; // 必须写 return
}
  • 实际场景
  1. 回调函数
// 不处理回调的返回值
arr.forEach((item): void => {
  console.log(item);
});

// 错误:回调返回了值,但类型要求 void
// forEach 要求 (item) => void,返回值被忽略
const nums = [1, 2, 3];
nums.forEach((n) => n * 2); // 不报错,但返回值被忽略
  1. 接口方法
interface Logger {
  log(msg: string): void; // 只要求调用,不要求返回值
  error(msg: string): void;
}

class ConsoleLogger implements Logger {
  log(msg: string) {
    console.log(msg);
    // 不需要 return
  }
  error(msg: string) {
    console.error(msg);
  }
}
  1. 泛型约束中的忽略
// Promise<void>:异步操作完成,但没有结果值
async function save(): Promise<void> {
  await fetch("/api/save");
  // 没有 return
}

// 对比
async function load(): Promise<string> {
  const res = await fetch("/api/data");
  return res.text(); // 返回 string
}
  • 注意点
// void 的返回值可以被赋值为 undefined
const x: void = undefined;

// 但 void 类型的表达式不能赋值给其他类型
function f(): void {}
const a: number = f(); // Error: Type 'void' is not assignable to type 'number'

// 箭头函数简写要注意
const handler1 = () => console.log(1); // () => void
const handler2 = () => {
  console.log(1);
}; // () => void
const handler3 = () => 1; // () => number
  • 总结:

void 表达"执行操作,不期待结果"。函数签名用它,调用方就知道不需要处理返回值。

1

评论区