目录
枚举类型
TypeScript泛型介绍
🎲泛型的基本使用
🎲泛型接口的使用
🎲泛型类的使用
🎲泛型的类型约束
总结:
枚举类型(Enum)详细介绍
定义枚举类型
使用枚举类型
注意事项
泛型(Generics)详细介绍
基本语法
泛型类和接口
泛型约束
枚举类型
枚举类型是为数不多的TypeScript特有的特性之一, JavaScript是没有的:
枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型;
枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型;
枚举类型使用
enum关键字
定义, 建议枚举中定义的值使用大写
枚举我们常见的使用方式如下
enum Direction {LEFT,RIGHT,TOP,BOTTOM
}function turnDirection(direction: Direction) {switch (direction) {case Direction.LEFT:console.log("转向左边")break;case Direction.RIGHT:console.log("转向右边")break;case Direction.TOP:console.log("转向上边")break;case Direction.BOTTOM:console.log("转向下边")break;default:const foo: never = directionbreak;}
}// 测试
turnDirection(Direction.LEFT)
turnDirection(Direction.RIGHT)
turnDirection(Direction.TOP)
turnDirection(Direction.BOTTOM)
枚举类型默认是有值的,比如上面代码的枚举,默认值其实是这样的:
enum Direction {LEFT = 0,RIGHT = 1,TOP = 2,BOTTOM = 3
}
当然,我们也可以给枚举其他值, 比如我们给LEFT一个值: 100
enum Direction {LEFT = 100,RIGHT,TOP,BOTTOM
}
这个时候LEFT后面的值如果没有设置值的话, 它们的默认值会从100进行递增, 相当于下面这样:
enum Direction {LEFT = 100,RIGHT = 101,TOP = 102,BOTTOM =103
}
我们也可以给他们赋值其他的类型:
enum Direction {LEFT,RIGHT,TOP = "TOP",BOTTOM = "BOTTOM"
}
TypeScript泛型介绍
🎲泛型的基本使用
软件工程的主要目的是构建不仅仅明确和一致的API,还要让你的代码具有很强的可重用性:
比如我们可以通过函数来封装一些API,通过传入不同的函数参数,让函数帮助我们完成不同的操作;
但是对于参数的类型是否也可以参数化呢?
什么是类型的参数化?
我们来提一个需求:封装一个函数,传入一个参数,并且返回这个参数;
如果我们是TypeScript的思维方式,要考虑这个参数和返回值的类型需要一致:
// 传入number类型, 返回number类型
function foo(arg: number): number {return arg
}
上面的代码虽然实现了,但是不适用于其他类型,比如string、 boolean、 Person等其他类型:
为了适用于其他类型, 我们可以定义为any类型
// 传入number类型, 返回number类型
function foo(arg: any): any {return arg
}
虽然any是可以的,但是定义为any的时候,我们其实已经丢失了类型信息:
比如我们传入的是一个number,那么返回的也是是any类型, 我们并不是希望它返回number类型,我们希望返回number类型;
我们想要做到在函数中可以捕获到参数的类型是number,并且同时使用它来作为返回值的类型;
我们需要在这里使用一种特性的变量 - 类型变量( type variable),它作用于类型,而不是值:
我们可以将它看做额外的一个参数;
它可以做到, 在定义这个函数时, 不决定这些参数的类型, 而是让调用者以参数的形式告知, 这里的函数参数应该是什么类型
function foo<Type>(arg: Type): Type {return arg
}
这里我们可以使用两种方式来调用它:
- 方式一:通过 <类型> 的方式将类型传递给函数;
foo<number>(123) // 传入number类型
foo<{name: string}>({ name: "chenyq" }) // 传入有name属性的对象类型
foo<number[]>([10, 20]) // 传入number类型的数组
- 方式二:通过类型推导,自动推导出我们传入变量的类型:
在这里会推导出它们是字面量类型的,因为字面量类型对于我们这个函数也是适用的
foo(50)
foo("aaa")
foo({ name: "kaisa" })
当然我们也可以传入多个类型:
function foo<T, E>(arg1: T, arg2: E) {console.log(arg1, arg2)
}foo<number, string>(123, "abc")
平时在开发中我们可能会看到一些常用的名称:
T: Type的缩写,类型
K、 V: key和value的缩写,键值对
E: Element的缩写,元素
O: Object的缩写,对象
🎲泛型接口的使用
在定义接口的时候我们也可以使用泛型:
// 定义泛型接口
interface IPerson<T1, T2> {name: T1age: T2
}const p: IPerson<string, number> = {name: "chenyq",age: 18
}
泛型接口是没有类型推导的, 但是可以有默认值类型的
// 泛型接口定义默认类型
interface IPerson<T1 = string, T2 = number> {name: T1age: T2
}const p: IPerson = {name: "chenyq",age: 123
}
🎲泛型类的使用
我们也可以编写一个泛型类
class Point<T> {x: Ty: Tz: Tconstructor(x: T, y: T, z: T) {this.x = xthis.y = ythis.z = z}
}// 泛型类是可以自动推导类型的
const p1 = new Point("1.22", "3.56", "7.32")
// 也可以自己指定类型, 有下面两种方式
const p2 = new Point<number>(10, 20, 30)
const p3: Point<string> = new Point("1.22", "3.56", "7.32")
🎲泛型的类型约束
有时候我们希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中:
比如string和array都是有length的,或者某些对象也是会有length属性的, 但是此时使用泛型, 编译阶段是会报错的, 因为不能保证泛型的所有类型都是有length属性的;
那么只要是拥有length的属性都可以作为我们的参数类型,而没有length属性的不允许作为参数, 那么应该如何操作呢?
我们可以使用接口定义一个对象类型, 对象类型要求必须有length属性, 在让泛型继承自这个接口
interface ILength {length: number
}// 泛型继承自接口
function getLength<T extends ILength>(arg: T) {console.log(arg.length)
}// 测试
// getLength(123) // 123没有length无法传入
getLength("abc") // 3
getLength([10, 20, 30]) // 3
getLength({ length: 10 }) // 10
总结:
枚举类型(Enum)详细介绍
在 TypeScript 中,枚举类型(Enum)用于定义一组命名的常量。枚举通过使用标识符来引用每个常量,并且可以具有相关联的数值。以下是枚举类型的详细介绍:
定义枚举类型
enum Direction {Up = 1,Down,Left,Right,
}
以上代码定义了一个名为 Direction
的枚举类型,它包含四个常量:Up
、Down
、Left
和 Right
。每个常量可以关联一个数值,默认情况下从 0 开始。
使用枚举类型
let userDirection: Direction = Direction.Up;
console.log(userDirection); // 输出 1
在这个示例中,我们声明了一个变量 userDirection
,并将其赋值为 Direction.Up
。这样就可以使用枚举类型中定义的常量来代表相应的数值。
注意事项
- TypeScript 中的枚举类型可以是数字枚举或字符串枚举。
- 数字枚举会自动增长成员的值,而字符串枚举的每个成员都必须被初始化。
- 枚举类型可以作为参数传递给函数,以及与其他枚举类型进行比较。
泛型(Generics)详细介绍
泛型是 TypeScript 中非常强大和灵活的特性,它允许创建可重用的组件,能够在多种数据类型上进行操作而不失去类型安全性。以下是泛型的详细介绍:
基本语法
function identity<T>(arg: T): T {return arg;
}
以上代码定义了一个简单的泛型函数 identity
,它接受一个类型为 T
的参数,并返回相同的类型。在调用时,编译器会根据传入的实际参数推断出 T
的具体类型。
泛型类和接口
interface GenericIdentityFn<T> {(arg: T): T;
}class GenericNumber<T> {zeroValue: T;add: (x: T, y: T) => T;
}
除了函数外,泛型还可以应用于类和接口。在上面的示例中,我们定义了一个泛型接口 GenericIdentityFn
和一个泛型类 GenericNumber
,它们都能够适用于不同类型的数据。
泛型约束
interface Lengthwise {length: number;
}function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length);return arg;
}
通过使用泛型约束,我们可以限定泛型类型只能是满足特定条件的类型。在上面的示例中,loggingIdentity
函数要求泛型类型必须包含一个名为 length
的属性。
总之,枚举类型和泛型分别提供了在 TypeScript 中定义一组常量和编写可重用的通用代码的方式。它们都能够提高代码的可读性、灵活性和安全性,是 TypeScript 中值得深入学习和应用的重要特性。