TypeScript 中的 Set:从基础到实战
一、什么是 Set?
Set 是 ES6 引入的有序列表集合,TS 完全继承并强化了它的类型特性,核心特点只有两个:
1.元素唯一性:自动去重,不会存储重复的值(包括基本类型和引用类型,规则不同)
2.无索引:和数组不同,Set 没有下标,不能通过 set[0] 取值
3.可迭代:支持 for...of、展开运算符等遍历方式
简单说:Set = 无重复值的集合,TS 给它加上了严格的类型校验,比 JS 原生 Set 更安全。
二、TypeScript 中 Set 的基础语法
(1)创建 Set(无初始值)
TS 中创建 Set 必须指定类型参数(泛型),这是和 JS 最大的区别,语法:
// 格式:new Set<类型>()
const emptySet = new Set<string>(); // 存储字符串类型的 Set
const numSet = new Set<number>(); // 存储数字类型的 Set
const boolSet = new Set<boolean>(); // 存储布尔类型的 Set
如果不指定类型,TS 会默认推断为 Set<unknown>,后续添加元素会报错,入门一定要养成指定类型的习惯。
(2)创建 Set(带初始值)
可以直接传入数组初始化 Set,TS 会自动校验数组元素类型:
// 字符串 Set
const strSet = new Set<string>(["苹果", "香蕉", "橙子", "苹果"]);
// 自动去重 → 最终值:{"苹果", "香蕉", "橙子"}
// 数字 Set
const numSet = new Set<number>([1, 2, 2, 3, 3, 3]);
// 自动去重 → 最终值:{1,2,3}
// 混合类型(不推荐,除非业务需要)
const mixSet = new Set<string | number>([1, "TS", 2, "TS"]);
(3)重要:Set 的去重规则
基本类型(string/number/boolean/null/undefined/Symbol):值相等就去重
引用类型(对象 / 数组):引用地址相等才去重(直接写两个对象不会去重)
// 基本类型去重(生效)
const set1 = new Set([1, 1, true, true, null, null]);
// 引用类型去重(不生效,因为地址不同)
const set2 = new Set([{ name: "TS" }, { name: "TS" }]);
console.log(set2.size); // 输出 2,两个对象地址不同
// 引用类型去重(生效,地址相同)
const obj = { name: "TS" };
const set3 = new Set([obj, obj]);
console.log(set3.size); // 输出 1
三、Set 的核心属性
Set 只有一个核心属性,入门必记:
size:获取 Set 中元素的个数(类似数组的 length)
const set = new Set<number>([1,2,3]);
console.log(set.size); // 输出 3
四、Set 的核心方法(全)
TS 中 Set 的方法和 JS 完全一致,但自带类型校验,传错类型会直接报错,这是 TS 的优势。
(1)add(value):添加元素
向 Set 中添加新元素,重复值会自动忽略,返回 Set 本身(支持链式调用)。
const set = new Set<string>();
set.add("TS");
set.add("Set");
set.add("TS"); // 重复,不生效
console.log(set); // Set(2) {"TS", "Set"}
// 链式调用
set.add("Vue").add("React");
TS 校验:只能添加指定类型的元素,否则编译报错
set.add(123); // ❌ 报错:类型“number”不能赋值给类型“string”
(2)delete(value):删除元素
删除指定元素,返回布尔值(删除成功:true,元素不存在:false)。
const set = new Set<number>([1,2,3]);
set.delete(2); // true
set.delete(4); // false
console.log(set); // Set(2) {1,3}
(3)has(value):判断元素是否存在
检查 Set 中是否包含指定元素,返回布尔值(高频使用,比数组的 includes 性能更高)。
const set = new Set<string>(["TS", "Set"]);
console.log(set.has("TS")); // true
console.log(set.has("JS")); // false
(4)clear():清空所有元素
清空 Set 中的所有元素,无返回值。
const set = new Set<number>([1,2,3]);
set.clear();
console.log(set.size); // 0
(5)keys() / values() / entries():获取迭代器
Set 中键和值是同一个,所以 keys() 和 values() 效果完全一致:
const set = new Set<string>(["TS", "Set"]);
// keys():返回键的迭代器
console.log(set.keys()); // SetIterator {"TS", "Set"}
// values():返回值的迭代器
console.log(set.values()); // SetIterator {"TS", "Set"}
// entries():返回 [键, 值] 迭代器(键=值)
console.log(set.entries()); // SetIterator {"TS" => "TS", "Set" => "Set"}
五、Set 的遍历方式(4 种常用)
Set 是可迭代对象,支持多种遍历方式,入门掌握前两种即可。
(1)for...of(最常用)
const set = new Set<number>([1,2,3]);
for (const item of set) {
console.log(item); // 依次输出 1、2、3
}
(2)forEach()(和数组用法一致)
const set = new Set<string>(["TS", "Set", "入门"]);
set.forEach((item) => {
console.log(item);
});
注意:Set 的 forEach 回调参数是 (value, key, set),因为无索引,key = value。
(3)展开运算符 ...(快速转数组)
const set = new Set<number>([1,2,3]);
const arr = [...set]; // [1,2,3]
(4)迭代器遍历
const set = new Set<number>([1,2,3]);
const iterator = set.values();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
六、TypeScript 中 Set 的高级类型用法
入门 TS,这几个类型场景一定要会,覆盖 90% 开发需求。
(1)存储对象类型(自定义接口)
Set 可以存储对象,必须用接口(interface) 约束类型,这是 TS 核心用法:
// 定义用户接口
interface User {
id: number;
name: string;
}
// 创建存储 User 类型的 Set
const userSet = new Set<User>([
{ id: 1, name: "张三" },
{ id: 2, name: "李四" },
]);
// 添加元素(必须符合 User 类型)
userSet.add({ id: 3, name: "王五" });
// 遍历对象 Set
userSet.forEach(user => {
console.log(user.id, user.name);
});
(2)联合类型 Set
存储多种指定类型的元素:
// 存储 string 或 number 类型
const unionSet = new Set<string | number>(["TS", 123, "Set", 456]);
(3)只读 Set(ReadonlySet)
禁止修改的 Set,不能调用 add/delete/clear,适合常量集合:
const readOnlySet: ReadonlySet<number> = new Set([1,2,3]);
readOnlySet.add(4); // ❌ 报错:ReadonlySet 没有 add 方法
七、Set 高频实战场景(入门必练)
(1)数组去重(最简单)
const arr = [1,2,2,3,3,3,4];
const uniqueArr = [...new Set(arr)]; // [1,2,3,4]
(2)判断数组是否包含重复值
function hasDuplicate<T>(arr: T[]): boolean {
return new Set(arr).size !== arr.length;
}
console.log(hasDuplicate([1,2,3])); // false
console.log(hasDuplicate([1,2,2])); // true
(3)集合运算:并集、交集、差集
const setA = new Set<number>([1,2,3]);
const setB = new Set<number>([2,3,4]);
// 并集(合并两个 Set,去重)
const union = new Set([...setA, ...setB]); // {1,2,3,4}
// 交集(两个 Set 都有的元素)
const intersection = new Set([...setA].filter(item => setB.has(item))); // {2,3}
// 差集(setA 有,setB 没有的元素)
const difference = new Set([...setA].filter(item => !setB.has(item))); // {1}
(4)字符串去重
const str = "typescript";
const uniqueStr = [...new Set(str)].join(""); // "typescrip"
八、Set vs WeakSet
WeakSet 是 Set 的弱引用版本:
(1)Set
1.存储类型:任意类型(基本 + 引用)
2.引用方式:强引用(对象不会被垃圾回收)
3.核心方法:add/delete/has/size/clear
4.遍历:支持所有遍历方式
5.使用场景:通用集合存储
(2)WeakSet
1.存储类型:只能存储对象
2.引用方式:弱引用(对象无引用时自动回收)
3.核心方法:add/delete/has(无 size,无 clear)
4.遍历:不可遍历
5.使用场景:临时对象缓存、不影响垃圾回收
// WeakSet 用法(只能存对象)
const weakSet = new WeakSet();
const obj = { name: "TS" };
weakSet.add(obj);
console.log(weakSet.has(obj)); // true
九、Set 常见坑(入门避坑)
引用类型不自动去重:直接存两个相同对象不会去重,需要手动判断地址
不能通过索引取值:set[0] 是 undefined,必须转数组或遍历
TS 类型必须一致:添加不同类型元素会直接报错
size 是属性不是方法:别写 set.size(),正确写法 set.size
更多推荐


所有评论(0)