🤔 问题描述
将两个数组合并成一个新数组。这就像是在 JavaScript 中使用 Array.concat() 方法一样。
📝 举个例子
// 我们想要实现这样的效果:
type Result = Concat<[1], [2]>; // 得到 [1, 2]
// 更多例子
type Example1 = Concat<[1, 2], [3, 4]>; // 得到 [1, 2, 3, 4]
type Example2 = Concat<[], [1]>; // 得到 [1]
type Example3 = Concat<['hello'], ['世界']>; // 得到 ['hello', '世界']
🔨 实现方案
type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U]
🎓 知识点解析
- 扩展运算符(...)
- 在
TypeScript类型中,...的作用和JavaScript中一样 - 可以展开数组中的所有元素
- extends 关键字
extends用来限制类型T extends readonly any[]表示T必须是一个数组类型
- readonly 修饰符
readonly表示数组是只读的- 使用
readonly可以兼容更多类型的数组
🌰 使用示例
// 基础用法
type Result1 = Concat<[1], [2]>
// 合并多个元素
type Result2 = Concat<[1, 2], [3, 4]>
// 使用不同的类型
type Result3 = Concat<[1, '2'], [true]>
// 使用只读数组
type Result4 = Concat<readonly [1], readonly [2]>
🎯 加 readonly 和不加 readonly 的区别是什么
1. 类型兼容性
// 定义一个只读数组
const readArr = [1, 2, 3] as const;
// 不加 readonly 版本
type ConcatWithoutReadonly<T extends any[], U extends any[]> = [...T, ...U]
type Result1 = ConcatWithoutReadonly<typeof readArr, [4]> // ❌ 报错!
// 加 readonly 版本
type ConcatWithReadonly<T extends readonly any[], U extends readonly any[]> = [...T, ...U]
type Result2 = ConcatWithReadonly<typeof readArr, [4]> // ✅ 正常工作
2. 为什么会这样
TypeScript 的类型系统中:
readonly array不能赋值给array- 但是
array可以赋值给readonly array
就像这样:
type Test1 = readonly any[] extends any[] ? true : false // false
type Test2 = any[] extends readonly any[] ? true : false // true
3. 示例
// 场景1:普通数组
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// 场景2:const 断言创建的只读数组
const arr3 = [1, 2, 3] as const;
const arr4 = [4, 5, 6] as const;
// 不加 readonly 的版本
type NormalConcat<T extends any[], U extends any[]> = [...T, ...U];
type Test1 = NormalConcat<typeof arr1, typeof arr2>; // ✅ 正常
type Test2 = NormalConcat<typeof arr3, typeof arr4>; // ❌ 报错
// 加 readonly 的版本
type ReadonlyConcat<T extends readonly any[], U extends readonly any[]> = [...T, ...U];
type Test3 = ReadonlyConcat<typeof arr1, typeof arr2>; // ✅ 正常
type Test4 = ReadonlyConcat<typeof arr3, typeof arr4>; // ✅ 正常
📝 实践建议
✅ 推荐使用 readonly 版本因为:
- 更好的类型兼容性。
- 可以处理所有数组类型。
- 支持
as const断言的数组。
❌ 不加 readonly 的限制:
- 不能处理只读数组。
- 不能处理
as const断言的数组。 - 类型兼容性较差。