Skip to content

TS

  • TypeScript是JavaScript的超集,主要通过静态类型检查的能力在编译阶段发现JS代码问题
  • TS中的module与ES Module类似,通过import和export导入导出,但TS中可以通过 declare module 来声明外部依赖
  • 枚举用来定义一个常量组合,默认每一项值为数字,也可以单独设置每一项值
  • Interface和type都可以用来表示对象或者函数类型,且可以相互继承
  • 多个同名interface会进行属性合并,type不行
  • type还可以声明其他基本类型,interface不行
  • Omit用于从一个复杂类型中剔除某些属性,Pick用于从其中指定某些属性
  • 泛型用于通用类型,由外部调用者自己控制调用函数(或类)中的参数类型

namespace vs module

  • namespace 是为了解决命名冲突的问题,本质是一个对象,将一系列相关的全局变量组织到一个对象的属性。使用export导出变量。有ES6后,官方已经不推荐使用namespace了。
  • module是ts中代码管理的方式。任何包括import或export语句的文件都是module。

装饰器

  • 格式:@后面是个函数名。函数接受所修饰对象的一些相关值为参数,函数要么不返回值,要么返回一个新对象取得目标对象。
  • 分为类装饰器、方法装饰器、属性装饰器。
  • 多个装饰器,先执行内层装饰器。
  • 在2022年分为新旧装饰器语法,但目前大量使用的是旧装饰器语法。
  • 新装饰器参数是:value(所装饰的对象)、context(上下文)
  • 旧装饰器参数是:类装饰器:target
  • 方法属性装饰器:target、方法名/属性名

运算符

  • keyOf
  • in
  • 方括号运算符[]:从对象取出属性的类型,
  • is :说明关系 如果A is B 则返回true
  • extends...?:三目运算符

Exclude<a, b>

  • 排除a中的b

type vs interface

  • 拓展方式: &,extends
  • 合并声明:interface支持
  • 表示范围:interface只能定义对象
  • 默认值:type可以定义默认值
  • 使用范围:type可以在函数内部使用

ts 中 any 和 unknown

  • any 类型是一种“逃脱类型检查”的类型。当一个变量被声明为 any 类型时,你可以对它进行任何操作,包括调用任意属性或方法,而不会收到 TypeScript 编译器的任何错误提示。
  • unknown 类型表示该变量的类型是未知的,它是一种安全的“多类型”类型。对 unknown 类型的变量进行操作时,必须进行类型检查或类型断言(如 typeof),否则 TypeScript 编译器会报错。
  • unknown 可以看作是更安全的 any。一般来说,凡是需要设为 any 类型的地方,通常都应该优先考虑设为 unknown 类型

高阶用法汇总

1. 高级类型

  1. 联合类型:使用 | 来表示一个变量可以是多种类型中的一种
    ts
    let value: string | number;
    value = "Hello";
    value = 42;
  2. 交叉类型:使用 & 来表示一个变量同时具有多种类型的·
    ts
    type A = {
         a1: string;
    }
    type B = {
         b1: number;
    }
    let value: A & B = { a1: "Hello", b1: 42 };

2. 范型

  • 泛型是指在定义函数或类时不预先指定具体的类型,而是在使用时再指定类型。这样可以使代码更加灵活和可重用。
ts
// 泛型函数
function identity<T>(arg: T): T {
  return arg;
}

// 泛型类
class Box<T> {
  private value: T;
  constructor(value: T) {
    this.value = value;
  }
  getValue(): T {
    return this.value;
  }
}

3. 映射类型

  • 映射类型是指通过对已有类型进行转换来创建新类型。常用的映射类型有 Partial、Required、Readonly、Record 等。
- Partial<T>:使所有属性可选。
- Readonly<T>:使所有属性只读。
- Pick<T, K>:选择部分属性。
- Omit<T, K>:排除部分属性。
- Record<K, T>:创建拥有指定属性的类型
ts
// Partial:将所有属性变为可选
type Partial<T> = {
    [P in keyof T]?: T[P];
};

// 将 T 中的所有属性变为只读属性
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

4. 条件类型

  • 条件类型能够依据条件来选择类型,语法类似于三元表达式。
ts
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false

5. 装饰器

  • 装饰器是一个特殊的类型声明,可以用来修改类、方法、属性等的行为。装饰器可以用于依赖注入、日志记录等场景。
ts
// 类装饰器示例
function logClass(target: Function) {
  console.log(`Class created: ${target.name}`);
}

@logClass
class MyClass {}

6. 命名空间

  • 命名空间是 TypeScript 中的一种组织代码的方式,可以将相关的代码组织在一起,避免全局命名冲突。命名空间可以包含变量、函数、类等。
ts
namespace Validation {
  export interface Validator {
    isValid(s: string): boolean;
  }
  export class EmailValidator implements Validator {
    isValid(email: string) {
      return email.includes('@');
    }
  }
}

// 使用
const validator: Validation.Validator = new Validation.EmailValidator();

7. 索引签名

  • 索引签名允许对象使用任意数量的属性,并且这些属性的类型可以是相同的。
ts
interface StringArray {
  [index: number]: string; // 索引签名
}
const myArray: StringArray = ["Hello", "World"];

demo

  1. 若要实现一个函数,使其在传入 User 对象的键名(如 'name')时返回对应值的类型,可通过 泛型 + keyof + 索引访问类型 组合实现。以下是具体实现步骤和代码:
ts
// T:任意对象类型,K:T 的键名
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

// 使用示例
const person = { name: "Bob", age: 25, isAdmin: true };

// 类型推导:result 为 string
const result = getProperty(person, "name");