

昨天写代码时,后端问我,“TypeScript 真的能保证代码没问题?” 我心想这问题咋答——类型检查再厉害也不能替代逻辑正确性啊。但后来想了想,TypeScript 有些高级功能确实可以让代码更清晰、更优雅,甚至把逻辑错误扼杀在摇篮里。于是今天就把这些进阶技巧分享出来,让你的代码像艺术品一样优雅!
写代码时难免遇到联合类型,怎么让代码智能点、少写点判断?类型守卫是你的好帮手。
typeof适合基本数据类型:
function processInput(input: string | number) {
if (typeof input === "string") {
console.log(`输入的是字符串,长度为 ${input.length}`);
} else {
console.log(`输入的是数字,加10变成 ${input + 10}`);
}
}in判断某个属性是否存在对象中:
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim();
} else {
animal.fly();
}
}更灵活、更强大:
function isFish(animal: Fish | Bird): animal is Fish {
return (animal as Fish).swim !== undefined;
}
function move(animal: Fish | Bird) {
if (isFish(animal)) {
animal.swim();
} else {
animal.fly();
}
}泛型是 TypeScript 的灵魂之一,进阶用法让你写出的工具函数更优雅。
限制泛型的类型范围:
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(arg: T): T {
console.log(`长度是:${arg.length}`);
return arg;
}
logLength([1, 2, 3]); // OK
logLength("Hello"); // OK
logLength(123); // 报错根据条件生成不同类型:
type IsString<T> = T extends string ? "是字符串" : "不是字符串";
type A = IsString<string>; // 是字符串
type B = IsString<number>; // 不是字符串有时候,我们需要修改一个类型的属性,手动写太麻烦,这时就可以用 映射类型。
快速生成只读类型:
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
interface User {
name: string;
age: number;
}
const user: Readonly<User> = { name: "张三", age: 25 };
// user.name = "李四"; // 报错:不能修改只读属性TypeScript 自带很多工具类型,比如 Partial、Pick、Omit:
type PartialUser = Partial<User>; // 所有属性变为可选
type PickUser = Pick<User, "name">; // 只保留 name 属性
type OmitUser = Omit<User, "age">; // 删除 age 属性这些工具类型让代码变得高效且优雅。
keyof 和索引类型:动态处理对象属性keyof 获取对象类型的键keyof 返回一个类型的所有键:
type User = { name: string; age: number };
type UserKeys = keyof User; // "name" | "age"
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "李四", age: 30 };
console.log(getProperty(user, "name")); // OK
console.log(getProperty(user, "age")); // OK适用于动态键值对:
type Dictionary = { [key: string]: string };
const colors: Dictionary = {
red: "#FF0000",
green: "#00FF00",
blue: "#0000FF",
};处理嵌套结构时大有用处:
type NestedArray<T> = T | NestedArray<T>[];
const arr: NestedArray<number> = [1, [2, [3, 4]]];写一个工具类型,把对象所有属性都变成只读,包括嵌套属性:
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
interface User {
name: string;
address: { city: string; street: string };
}
const user: DeepReadonly<User> = {
name: "张三",
address: { city: "北京", street: "长安街" },
};
// user.address.city = "上海"; // 报错:只读属性看完是不是觉得 TypeScript 的功能层次感十足? 用类型守卫优化逻辑判断,用高级泛型提高代码复用性,用映射类型批量改造类型结构,还有递归类型玩转嵌套属性,每一项都让你的代码更智能、更优雅。
TypeScript 的强大不止于此,真正用起来才会发现它的魅力!快把这些进阶技巧用在你的项目里吧,写出让后端大呼“大神”的代码~
如果你也遇到过 TypeScript 的类型问题,欢迎评论分享交流,我会第一时间回复!