类型运算符(typeof)
在 TypeScript
中,typeof
操作符不仅可以用于获取值的运行时类型,还可以在类型上下文中使用,获取变量或属性的编译时类型。
基础示例
ts
const person = { name: "兜兜", age: 18 };
// 使用 typeof 获取 person 对象的类型
type Person = typeof person;
/*
Person 类型等价于:
{
name: string;
age: number;
}
*/
function updatePerson(p: Person) {
// p 的类型是 { name: string; age: number; }
}
复杂对象类型获取
ts
const userInfo = {
id: 1,
name: "兜兜",
roles: ["admin", "user"] as const,
permissions: { read: true, write: false, delete: false },
createdAt: new Date(),
};
// 使用 typeof 获取复杂对象的完整类型
type UserInfoType = typeof userInfo;
/* UserInfoType 等价于:
{
id: number;
name: string;
roles: readonly ["admin", "user"];
permissions: {
read: boolean;
write: boolean;
delete: boolean;
};
createdAt: Date;
}
*/
函数类型获取
Parameters
获取函数参数类型ReturnType
获取函数返回值类型
ts
function calculateTotal(items: { price: number; quantity: number }[]) {
return items.reduce((total, item) => total + item.price * item.quantity, 0);
}
// 获取函数的类型
type CalculateTotalType = typeof calculateTotal;
// 获取函数参数类型
type CalculateTotalParams = Parameters<typeof calculateTotal>;
// 获取函数返回值类型
type CalculateTotalReturnType = ReturnType<typeof calculateTotal>;
// 使用示例
const items = [
{ price: 10, quantity: 2 },
{ price: 5, quantity: 3 },
];
const total: CalculateTotalReturnType = calculateTotal(items); // number
类和构造函数类型
ts
class UserAccount {
name: string;
id: number;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
getInfo() {
return `${this.name} (${this.id});`;
}
}
const userInstance = new UserAccount("兜兜", 1);
// 获取实例类型
type UserInstanceType = typeof userInstance;
// 获取类的构造函数类型
type UserClassType = typeof UserAccount;
// 使用类构造函数类型创建工厂函数
function createUser(ctor: UserClassType, name: string, id: number): InstanceType<UserClassType> {
return new ctor(name, id);
}
const newUser = createUser(UserAccount, "Murphy", 2);
枚举类型获取
ts
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
// 获取枚举类型
type DirectionType = typeof Direction;
// 在运行时使用枚举
function move(direction: Direction) {
switch (direction) {
case Direction.Up:
console.log("Moving up");
break;
case Direction.Down:
console.log("Moving down");
break;
}
}
// 使用 typeof 获取枚举成员的类型
type DirectionValue = DirectionType[keyof DirectionType];
数组和元组类型获取
ts
const COLORS = ["red", "green", "blue"] as const;
// 获取数组类型
type ColorsType = typeof COLORS;
// COLORS 的类型是 readonly ["red", "green", "blue"]
// 而不是 string[]
// 使用 typeof 创建基于常量数组的类型
type Color = (typeof COLORS)[number]; // "red" | "green" | "blue"
const validColors: Color[] = ["red", "green"]; // 只能是 COLORS 中的值
结构类型(interface)
ts
// noinspection JSAnnotator
interface User {
name: string;
id: number;
}
const user: User = {
name: "兜兜",
id: 2,
};
类使用接口声明
ts
interface User {
name: string;
id: number;
}
class UserAccount {
name: string;
id: number;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
const user: User = new UserAccount("Murphy", 1);
函数定义
ts
interface User {
name: string;
id: number;
}
function getAdminUser(): User {
//...
}
function deleteUser(user: User) {
// ...
}
继承(extends)
ts
interface User {
name: string;
id: number;
}
interface AdminUser extends User {
isAdmin: boolean;
}
const user: AdminUser = {};
组合类型 (|)
ts
type MyBool = true | false;
function getLength(obj: string | string[]) {
return obj.length;
}
泛型(<>)
泛型为类型提供变量。一个常见的例子是数组。没有泛型的数组可以包含任何东西。具有泛型的数组可以描述数组包含的值。
ts
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
可忽略参数 (?)
在函数中,我们可以使用?来表示一个参数是可选的。
ts
function f(x: number, y?: number) {
return x + (y || 0);
}
非空断言 (!)
!
是 TypeScript 的一个类型层面的操作符,用于告诉编译器:“我非常确定这个变量在此时不是null
也不是undefined
”,因此可以安全使用其属性或方法,不会报类型错误。- 它只在编译阶段有效,编译后会被移除,对最终 JS 输出不起任何作用。
ts
a!.data;
a!.data.length;
交叉类型 (&)
交叉类型(Intersection Types)通过 &
运算符将多个类型合并为一个,表示同时具备所有类型的所有属性和方法。
typescript
interface Dog {
dogName: string;
dogAge: number;
}
interface Cat {
catName: string;
catAge: number;
}
type Pet = Dog & Cat;
const pet: Pet = {
dogName: "Murphy",
dogAge: 2,
catName: "Murphy",
catAge: 2,
};
缺省运算 (Omit)
使用 Omit
运算符可以删除对象中的某些属性。
typescript
type Pet = {
dogName: string;
dogAge: number;
catName: string;
catAge: number;
};
// 删除 catName 和 catAge
type Dog = Omit<Pet, "catName" | "catAge">;
挑选运算 (Pick)
使用 Pick
运算符可以挑选对象中的某些属性。
typescript
type Pet = {
dogName: string;
dogAge: number;
catName: string;
catAge: number;
};
type Dog = Pick<Pet, "dogName" | "dogAge">;
可选运算 (Partial)
使用 Partial
运算符可以将所有属性变为可选。
typescript
type Pet = {
dogName: string;
dogAge: number;
catName: string;
catAge: number;
};
type Dog = Partial<Pet>;
Optional的实现及原理
原理:
K extends keyof T
:表示K
必须是"name" | "age" | "email" | "isAdmin"
中的一个或多个Pick<T, K>
:从T
中挑选出指定的K
属性,返回一个新类型Partial<...>
:将Pick
出来的属性变成可选的Omit<T, K>
:从原始类型T
中排除掉K
属性- 最后将
Omit
和Partial
的结果通过交叉类型&
组合起来
typescript
interface User {
name: string;
age: number;
email: string;
isAdmin: boolean;
}
interface UserOptional {
name?: string;
age?: number;
}
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type UserOptional = Optional<User, "name" | "age">;
记录类型(Record)
Record
是 TypeScript 中的一个实用类型,用于创建具有特定键值对类型的对象。它接受两个类型参数:键的类型和值的类型。
ts
// 示例:用户 ID 映射
type User = {
name: string;
id: number;
};
const users: Record<string, User> = {
u1: { name: "兜兜", id: 2 },
u2: { name: "Murphy", id: 1 },
};
你也可以使用 Record
创建简单的键值对集合:
ts
// 字符串到数字的映射
const scores: Record<string, number> = {
math: 90,
english: 85,
science: 92,
};
使用联合类型作为键
你可以通过联合类型来限制键的取值范围:
ts
type Color = "red" | "green" | "blue";
const colorHex: Record<Color, string> = {
red: "#FF0000",
green: "#00FF00",
blue: "#0000FF",
};
TypeScripthttps://blog.ddlyt.top/posts/2025/0509
评论 隐私政策