系列文章推荐:
相关文章推荐:
【5天学会TS】打卡学习Typescript的第一天-优快云博客
文章目录:
目录
6.1 Partial 用来构造(创建)一个类型,将 Type 的所有属性设置为可选
6.2 Readonly 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)
6.4 Record 构造一个对象类型,属性键为 Keys,属性类型为 Type
前言:
昨天学习了TS的数据类型,基于JS的类型有些扩展,今天重点学习泛型。泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
版本说明:
Node.js: 18.20.4
npm:10.7.0
具体内容:
1.泛型的使用意义:
- 代码重用: 可以编写与特定类型无关的通用代码,提高代码的复用性。
- 类型安全: 在编译时进行类型检查,避免在运行时出现类型错误。
- 抽象性: 允许编写更抽象和通用的代码,适应不同的数据类型和数据结构。
2.泛型的标识符
T: 代表 "Type",是最常见的泛型类型参数名
function identity<T>(arg: T): T {
return arg;
}
K, V: 用于表示键(Key)和值(Value)的泛型类型参数
interface KeyValuePair<K, V> {
key: K;
value: V;
}
E: 用于表示数组元素的泛型类型参数
function printArray<E>(arr: E[]): void {
arr.forEach(item => console.log(item));
}
R: 用于表示函数返回值的泛型类型参数
function getResult<R>(value: R): R {
return value;
}
U, V: 通常用于表示第二、第三个泛型类型参数
function combine<U, V>(first: U, second: V): string {
return `${first} ${second}`;
}
这些标识符是约定俗成的,实际上你可以选择任何符合标识符规范的名称。
3.泛型应用
3.1 泛型函数
function identity<T>(arg: T): T {
return arg;
}
// 使用泛型函数
let result = identity<string>("Hello");
console.log(result); // 输出: Hello
let numberResult = identity<number>(42);
console.log(numberResult); // 输出: 42
3.2 泛型接口
// 基本语法
interface Pair<T, U> {
first: T;
second: U;
}
// 使用泛型接口
let pair: Pair<string, number> = { first: "hello", second: 42 };
console.log(pair); // 输出: { first: 'hello', second: 42 }
3.3 泛型类
// 基本语法
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
// 使用泛型类
let stringBox = new Box<string>("TypeScript");
console.log(stringBox.getValue()); // 输出: TypeScript
4.泛型约束
在这个例子中,定义了一个泛型函数 logLength
,它接受一个类型为 T
的参数,但有一个约束条件,即 T
必须实现 Lengthwise
接口,该接口要求有 length
属性。因此,可以正确调用 logLength("hello")
,但不能调用 logLength(42)
,因为数字没有 length
属性。
// 基本语法
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(arg: T): void {
console.log(arg.length);
}
// 正确的使用
logLength("hello"); // 输出: 5
// 错误的使用,因为数字没有 length 属性
logLength(42); // 错误
各个参数之间互相约束:
function copyFields<T extends U, U>(target: T, source: U): T {
for (let id in source) {
target[id] = (<T>source)[id];
}
return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
copyFields(x, { b: 10, d: 20 });
指定具体类型,将类型修改为 Type[](Type 类型的数组),因为只要是数组就一定存在 length 属性
function id<T>(value:T[]):T[]{
console.log(value.length)
return value
}
let idfirst = id([1,2,3])
console.log(idfirst)
// 3
// [1,2,3]
添加约束,传入参数必须有length属性
interface nober{
length:number,
}
function numberone<T extends nober>(arg:T):T{
console.log(arg.length)
return arg
}
let egone = numberone('happy')
console.log(egone)
// 5
// happy
5.泛型参数的默认类型
这个例子展示了带有默认值的泛型函数。函数 defaultValue
接受一个泛型参数 T
,并给它设置了默认类型为 string
。
// 基本语法
function defaultValue<T = string>(arg: T): T {
return arg;
}
// 使用带默认值的泛型函数
let result1 = defaultValue("hello"); // 推断为 string 类型
let result2 = defaultValue(42); // 推断为 number 类型
6.泛型的工具类型
6.1 Partial 用来构造(创建)一个类型,将 Type 的所有属性设置为可选
interface data1{
id:string,
students:number[]
}
type data2 = Partial<data1>
let p1:data1 = {
id: 's1',
students: [1, 2]
}
let p2:data2 = {
id: 's2',
students: [1, 2, 3]
}
console.log(p1,p2)
6.2 Readonly 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)
interface data1{
id:string,
students:number[]
}
type data2 = Readonly<data1>
let p1:data2 = {
id: 's1',
students: [1, 2]
}
console.log(p1)
p1.id = 's3'
6.3 Pick从 Type 中选择一组属性来构造新类型
interface data1{
id:string,
students:number[]
title: string
}
type data2 = Pick<data1, 'id'|'students'>
let p1:data2 = {
id: 's1',
title: 'aaa', // title不在data2中
students: [1, 2]
}
console.log(p1)
6.4 Record 构造一个对象类型,属性键为 Keys,属性类型为 Type
用于创建具有特定键和值类型的对象映射
interface AppConfig {
port: number;
env: 'development' | 'production';
}
const config: Record<string, AppConfig> = {
server: { port: 3000, env: 'development' },
client: { port: 8080, env: 'production' },
};
type Scores = Record<'Math' | 'English' | 'Science', number>;
const studentScores: Scores = {
Math: 90,
English: 85,
Science: 92
};
enum Color {
Red,
Green,
Blue,
}
const colorNameMap: Record<Color, string> = {
[Color.Red]: 'Red',
[Color.Green]: 'Green',
[Color.Blue]: 'Blue',
};
最后
至此,本次的技术探索之旅暂告一段落,但技术的海洋浩瀚无垠,我们的征程远未结束。
如果你觉得这篇博客为你带来了新的视角、解决了你的困惑或者激发了你的思考,那么请不要吝啬你的点赞和收藏,让我们一起在技术的道路上携手前行,共同成长。
关注我的技术博客,未来还有更多精彩的技术分享和深度的探讨等待着大家。
每一次的点赞都是对我的鼓励
每一次的收藏都是知识的沉淀
让我们一起用技术的力量创造更美好的未来