Appearance
TypeScript 高级语法
枚举类型
枚举类型是一组可能出现的值列举出来 定义在一个类型中 这个类型就是枚举类型
枚举允许开发者定义一组命名常量 常量可以是数字也可以是字符串类型
ts
enum Direction {
UP,
DOWN,
LEFT,
RIGHT,
}
const dl: Direction = Direction.UP;
function turnDirection(direction: Direction) {
switch (direction) {
case Direction.LEFT:
console.log("");
break;
}
}
枚举类型设置值
ts
enum Direction {
LEFT = 'LEFT'
RIGHT = "RIGHT"
}
枚举类型默认值
枚举类型默认值从 0 开始 可以重新赋值
泛型
泛型表示泛指某一种类型 开发者可以指定一个表示类型的变量 用来作为实际类型的占位符 用尖括号来包裹这个类型变量 泛型的作用主要是创建可以重用的组件 从而让一个组件可以支持多种数据类型 它也可以作用在接口 类 函数 或者函数别名上
首先我们定义一个函数 让一个函数接受一个参数并直接返回这个参数
ts
function identity(value) {
return value;
}
console.log(identity(111)); // 111
然后我们在继续支持 typescript 类型的参数
ts
function identity(value: number): number {
return value;
}
console.log(identity(666));
这里我们将 number 类型分配给参数和返回类型 使得该函数可用于原始类型 但是该函数不是通用的 我们希望定义不同的类型 但是还不能使用 any 因为 any 会使得编译器失去类型保护的作用 我们目的是让 函数适合任意的类型 我们可以使用泛型
ts
function identity<T>(value: T): T {
return value;
}
console.log(identity<number>(1)); // 1
当我们调用函数的时候 number 类型 就像 参数 一样 会出现在 T 的任何位置进行填充 T 被称为类型变量 其中 T 代表 Type,在定义泛型时通常用作第一个类型变量名称。但实际上 T 可以用任何有效名称代替。除了 T 之外,以下是常见泛型变量代表的意思:
到底要传入什么类型,不能写死,要让用户自己传递上去,让用户传递一个类型,用户传递类型在函数名字得后面
ts
function identity<Type>(arg: Type): Type {
return arg;
}
const res1 = identity<number>(123);
const res2 = identity<string>("string");
const res3 = identity<{ name: string }>({ name: "ek" });
WARNING
T (type) 表示类型 K (Key) 表示对象中的键的类型 V (Value) 表示对象中值的类型 E (Element) 表示元素类型
而且 我们并不是只能定义一个类型变量 我们 可以引用定义希望的任何数量的类型变量 比如我们引用了一个类型变量 u 用于扩展我们定义的函数
ts
function identity <T U>(value: T, message: U): T {
console.log(message)
return value
}
console.log(identity<Number, string>(68, "erkelost"));
我们返回多种类型 可以使用元组
ts
function identity<T, U>(value: T, message: U): [T, U] {
return [value, message];
}
useState 的练习 react
ts
泛型接口
解决函数中返回多种类型对象的问题 我们可以创建一个用于 identity 函数通用接口
ts
interface Identities<V M> {
value: V
message:
}
ts
function identity<T, U>(value: T, message: U): Identities<T, U> {
console.log(value + ": " + typeof value);
console.log(message + ": " + typeof message);
let identities: Identities<T, U> = {
value,
message,
};
return identities;
}
console.log(identity(68, "Semlinker"));
泛型约束
我们可以限制类型变量对应类型上的某些属性
确保属性是否存在
ts
function identity<T>(arg: T): T {
// Property 'length' does not exist on type 'T'.(2339)
console.log(arg.length); // Error
return arg;
}
编译器没法确认 T 类型一定含有 length 属性,尤其是在可以将任何类型赋给类型变量 T 的情况下。需要做的就是让类型变量 extends 一个含有我们所需属性的接口 这时候会报错
ts
interface Length {
length: number;
}
function identity<T extends Length>(arg: T): T {
console.log(arg.length); // 可以获取length属性
return arg;
}
这时候 如果在调用这个函数 但是传递别的类型的值 就会报错 使用 ,逗号来分割多中的约束类型 T extends Length, Type2, Type3>
ts
// 使用其他数组也可以调用length
function identity<T>(arg: T[]): T[] {
console.log(arg.length);
return arg;
}
Extend
接口和类型别名都能够被扩展,但语法有所不同。此外,接口和类型别名不是互斥的。接口可以扩展类型别名,而反过来是不行的。
继承,一个新的接口或者类,从父类或者接口继承所有的属性和方法,不可以重写属性,但可以重写方法
ts
// 接口继承接口
interface Person {
name: string;
age?: number;
}
interface obj extends Person {
sex: number;
}
// 类型别名 继承
type PartialPointX = { x: number };
type Point = PartialPointX & { y: number };
Implements
implements 实现,一个新的类,从父类或者接口实现所有的属性和方法,同时可以重写属性和方法,包含一些新的功能
ts
interface Point {
x: number;
y: number;
}
class SomePoint implements Point {
x = 1;
y = 2;
}
type Point2 = {
x: number;
y: number;
};
class SomePoint2 implements Point2 {
x = 1;
y = 2;
}
Ts 映射类型 工具链
我们设定如果登录 需要 以下类型
ts
type user {
username: string
password: string
}
如果我们修改对象信息 只能修改密码 那么我们不需要 username 我们需要定义可选类型
ts
type UserPartial {
username?: string
password?: string
}
对于查看用户信息 所有都是只读属性
ts
type ReadonlyType {
readonly username?: string
readonly password?: string
}
这样代码就会有许多相同的 字段 我们这时候可以是用映射类型 他是一种泛型 Mapped Type 把原有的对象类型映射成为新的对象类型
映射类型语法
ts
{[P in K]: T}
// in 类似js中的 for in 语句 用于遍历k类型中的所有类型
// T 类型用于 表示ts中的任意类型
// 在映射的过程中我们还可以使用 readonly 和 ? 这两个额外的修饰符
// 映射类型 示例
type Item = { a: string; b: number; c: boolean }
type T1 = { [P in "X" | "Y"]:number}
// { x:number, y: number}
type T2 = { [P in "x" | "y"]: p}
// { x: 'x', y: 'y'}
type T3 = { [P in "a" | "b"] : Item[p]}
// { a: string, b: number}
type T4 = { [P in keyof Item]: item[P]}
// { a: string, b:number, c: boolean}