TypeScript

67 阅读5分钟

TypeScript知识点汇总

类型推论 | 类型别名

 什么是类型推论

允许编译器根据赋给变量的值或者函数调用的上下文来自动确定类型。这意味着在很多情况下,你不需要显式地为变量、参数或返回值指定类型,TypeScript 编译器能够自己推断出正确的类型

1.声明了一个变量,但是没有定义类型,Typescript会在没有明确的指定类型的时候推测出一个类型

但是不能赋值给别的类型

2.如果你声明变量没有定义类型也没有赋值这时候TS会推断成any类型可以进行任何操作

类型别名

type 关键字(可以给一个类型定义一个名字)多用于复合类型

type 和 interface 的区别

1.interface可以继承  type 只能通过 & 交叉类型合并

2.type 可以定义 联合类型 和 可以使用一些操作符 interface不行

3.interface 遇到重名的会合并 type 不行

Symbol类型

 在 TypeScript 中,symbol 是一种原始数据类型,类似于 JavaScript 的 ES6 引入的 Symbol 类型。它主要用于创建唯一的键名,通常用于对象的属性键,以避免键名冲突

  • 唯一性:每个 symbol 值都是独一无二的,即使它们是通过相同的描述符创建的。
  • 作为对象属性键symbol 可以用作对象属性的键,这可以防止属性名的冲突,因为 symbol 键不会被枚举。
  • 创建方式:使用 Symbol() 函数创建一个 symbol 类型的值。如果传入参数,该参数将作为 symbol 的描述符,但描述符并不影响 symbol 的唯一性。 
  • 只支持 string 和 number 类型的参数

示例代码 

const s1 = Symbol();
const s2 = Symbol('foo');
const s3 = Symbol('foo');

console.log(s1 === s2); // false
console.log(s2 === s3); // false

const obj = {
  [s1]: 'value1',
  [s2]: 'value2'
};

console.log(obj[s1]); // 'value1'
console.log(obj[s2]); // 'value2'

注意事项

  • symbol 类型不能与其他类型进行比较或运算,因为它们是不同的数据类型。
  • 当使用 for...in 循环或 Object.keys() 方法时,symbol 属性不会被枚举出来。
  • 如果需要在 JSON 字符串中序列化和反序列化包含 symbol 属性的对象,需要自定义序列化和反序列化逻辑,因为 JSON.stringify 和 JSON.parse 默认不处理 symbol 类型。

如何获取symbol定义的属性

  1. 使用方括号表示法: 你可以使用方括号表示法并传递 Symbol 键来访问属性。
   const mySymbol = Symbol('myKey');
   const obj = { [mySymbol]: 'value' };

   console.log(obj[mySymbol]); // 输出 'value'

     2. 使用 Reflect.get() : Reflect.get() 方法可以用来获取对象上任何键的值,包括那些由 Symbol 定义的键。

   const mySymbol = Symbol('myKey');
   const obj = { [mySymbol]: 'value' };

   console.log(Reflect.get(obj, mySymbol)); // 输出 'value'

      3. 使用 Object.getOwnPropertySymbols() : 这个方法返回一个数组,包含了对象上所有 Symbol 键的属性。之后你可以遍历这个数组来访问这些属性。

   const mySymbol = Symbol('myKey');
   const obj = { [mySymbol]: 'value' };

   const symbols = Object.getOwnPropertySymbols(obj);
   symbols.forEach(symbol => {
     console.log(Reflect.get(obj, symbol)); // 输出 'value'
   });

如何让两个symbol相等 

使用 Symbol.for() 方法

const sym1 = Symbol.for('myKey');
const sym2 = Symbol.for('myKey');

console.log(sym1 === sym2); // 输出 true

Symbol.for() 方法应该谨慎使用,因为它可能会导致全局命名空间的污染,尤其是当多个模块或库共享相同的 Symbol key 时

泛型

 TypeScript 的泛型是一种强大的类型系统特性,它允许你编写可重用的组件,这些组件可以操作各种不同的数据类型,同时仍然保持类型安全性。泛型使你能够在不知道具体类型的情况下编写函数、类和接口,而具体的类型则在使用时确定。

泛型的基本用法

  1. 泛型函数: 你可以定义一个带有类型参数的函数,这个类型参数可以在函数体内部使用,以适应不同类型的输入和输出。
   function identity<T>(arg: T): T {
       return arg;
   }

   let output = identity<string>("hello"); 

     2. 泛型类: 类也可以使用泛型,这样类的实例就可以有不同的类型。

   class GenericNumber<T> {
       zeroValue: T;
       add: (x: T, y: T) => T;
   }

     3. 泛型接口: 接口同样可以使用泛型,这样可以定义接受不同类型参数的方法。

   interface GenericIdentityFn<T> {
       (arg: T): T;
   }

   let myIdentity: GenericIdentityFn<number> = (x) => x;

泛型约束 

为了限制泛型的使用范围,你可以添加约束,确保泛型参数满足特定条件。例如,你可能想要确保泛型参数必须具有某个特定的方法或属性。

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

泛型参数的默认类型

可以为泛型参数提供默认类型,这样在使用泛型时不指定类型参数时,它会采用默认类型。

function identity<T = string>(arg: T): T {
    return arg;
}

let output = identity("hello");  

枚举

 在 TypeScript 中,enum 类型提供了一种定义一组命名的常量的便捷方式。enum 可以让你将一组相关的值组织在一起,并给它们赋予有意义的名称,这不仅提高了代码的可读性,还增加了类型安全性。下面是一些关于 TypeScript 中 enum 的关键点:

基本语法

enum Color { Red, Green, Blue }

在上面的例子中,Color 是一个枚举类型,它包含三个成员:RedGreen 和 Blue。默认情况下,第一个成员的值是 0,后续成员的值依次递增。

显式赋值

显式地为每个成员赋值:

enum Color { Red = 1, Green = 2, Blue = 4 }

混合使用数字和字符串

虽然枚举成员通常使用数字,但也可以使用字符串或甚至其他类型的值:

enum Direction {
    Up = "up",
    Down = "down",
    Left = "left",
    Right = "right"
}

反向映射

使用字符串或显式数值时,TypeScript 会自动创建反向映射,即从枚举成员的值到其名称的映射。这意味着你可以通过值来获取成员名称:

enum Color { Red = 1, Green = 2, Blue = 4 }

console.log(Color[2]); // 输出 "Green"

访问枚举成员

通过枚举类型的名字和成员的名字来访问枚举成员的值:

enum Color { Red, Green, Blue }

console.log(Color.Red); // 输出 0

枚举成员的迭代

使用 for...in 循环或 Object.keys() 来迭代枚举成员:

enum Color { Red, Green, Blue }

for (let color in Color) {
    if (typeof Color[color] === 'number') {
        console.log(color);
    }
}

枚举的使用场景

enum 在很多场景下都非常有用,比如定义状态码、错误代码、配置选项等。它们提供了一种清晰的方式来管理一组固定的、相关的值