- 发布于
TypeScript高级类型模式:泛型、条件类型与类型体操实战
- 作者

- 姓名
- 全能波
- GitHub
- @weicracker
TypeScript高级类型模式:泛型、条件类型与类型体操实战
TypeScript的类型系统功能强大,掌握高级类型模式能显著提升代码质量和开发体验。本文将分享TypeScript高级类型的实战技巧和最佳实践。
泛型高级应用
泛型约束与条件
// 基础泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
// 使用keyof约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const person = { name: 'Alice', age: 30, city: 'New York' };
const name = getProperty(person, 'name'); // string
const age = getProperty(person, 'age'); // number
// 多重泛型约束
interface Comparable<T> {
compareTo(other: T): number;
}
interface Serializable {
serialize(): string;
}
function processItem<T extends Comparable<T> & Serializable>(item: T): string {
// item既可比较又可序列化
return item.serialize();
}
// 条件泛型约束
type NonNullable<T> = T extends null | undefined ? never : T;
type Example1 = NonNullable<string | null>; // string
type Example2 = NonNullable<number | undefined>; // number
// 高级泛型工具类型
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
interface User {
id: number;
profile: {
name: string;
settings: {
theme: string;
notifications: boolean;
};
};
}
type ReadonlyUser = DeepReadonly<User>;
// 所有属性都变为只读,包括嵌套对象
// 泛型工厂模式
interface Repository<T> {
findById(id: string): Promise<T | null>;
save(entity: T): Promise<T>;
delete(id: string): Promise<void>;
}
class BaseRepository<T extends { id: string }> implements Repository<T> {
constructor(private entityName: string) {}
async findById(id: string): Promise<T | null> {
// 实现查找逻辑
console.log(`Finding ${this.entityName} with id: ${id}`);
return null;
}
async save(entity: T): Promise<T> {
console.log(`Saving ${this.entityName}:`, entity);
return entity;
}
async delete(id: string): Promise<void> {
console.log(`Deleting ${this.entityName} with id: ${id}`);
}
}
// 使用示例
interface Product {
id: string;
name: string;
price: number;
}
const productRepo = new BaseRepository<Product>('Product');
// 泛型单例模式
class Singleton<T> {
private static instances: Map<any, any> = new Map();
static getInstance<T>(this: new () => T): T {
if (!Singleton.instances.has(this)) {
Singleton.instances.set(this, new this());
}
return Singleton.instances.get(this);
}
}
class DatabaseConnection extends Singleton<DatabaseConnection> {
private constructor() {
super();
}
connect() {
console.log('Connected to database');
}
}
const db1 = DatabaseConnection.getInstance();
const db2 = DatabaseConnection.getInstance();
console.log(db1 === db2); // true
高级泛型模式
// 函数重载与泛型
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// 重载签名
function apiCall<T>(url: string): Promise<ApiResponse<T>>;
function apiCall<T>(url: string, options: RequestInit): Promise<ApiResponse<T>>;
function apiCall<T, U>(url: string, options: RequestInit, transform: (data: any) => U): Promise<ApiResponse<U>>;
// 实现签名
function apiCall<T, U = T>(
url: string,
options?: RequestInit,
transform?: (data: any) => U
): Promise<ApiResponse<T | U>> {
return fetch(url, options)
.then(response => response.json())
.then(data => ({
data: transform ? transform(data) : data,
status: 200,
message: 'Success'
}));
}
// 使用示例
interface User {
id: number;
name: string;
}
// 基础调用
const users = await apiCall<User[]>('/api/users');
// 带选项调用
const user = await apiCall<User>('/api/users/1', { method: 'GET' });
// 带转换调用
const userNames = await apiCall(
'/api/users',
{ method: 'GET' },
(users: User[]) => users.map(u => u.name)
);
// 泛型类装饰器
function Entity<T extends { new(...args: any[]): {} }>(tableName: string) {
return function(constructor: T) {
return class extends constructor {
tableName = tableName;
save() {
console.log(`Saving to table: ${this.tableName}`);
}
};
};
}
@Entity('users')
class User {
constructor(public name: string, public email: string) {}
}
const user = new User('Alice', 'alice@example.com');
user.save(); // Saving to table: users
// 泛型方法装饰器
function Cache<T>(ttl: number = 60000) {
return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const cache = new Map<string, { value: T; expiry: number }>();
descriptor.value = function(...args: any[]): T {
const key = JSON.stringify(args);
const cached = cache.get(key);
if (cached && Date.now() < cached.expiry) {
return cached.value;
}
const result = originalMethod.apply(this, args);
cache.set(key, { value: result, expiry: Date.now() + ttl });
return result;
};
};
}
class DataService {
@Cache<string[]>(30000) // 缓存30秒
getUsers(): string[] {
console.log('Fetching users from database...');
return ['Alice', 'Bob', 'Charlie'];
}
}
// 泛型事件系统
interface EventMap {
[key: string]: any;
}
class TypedEventEmitter<T extends EventMap> {
private listeners: { [K in keyof T]?: Array<(data: T[K]) => void> } = {};
on<K extends keyof T>(event: K, listener: (data: T[K]) => void): void {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]!.push(listener);
}
emit<K extends keyof T>(event: K, data: T[K]): void {
const eventListeners = this.listeners[event];
if (eventListeners) {
eventListeners.forEach(listener => listener(data));
}
}
off<K extends keyof T>(event: K, listener: (data: T[K]) => void): void {
const eventListeners = this.listeners[event];
if (eventListeners) {
const index = eventListeners.indexOf(listener);
if (index > -1) {
eventListeners.splice(index, 1);
}
}
}
}
// 定义事件类型
interface AppEvents {
userLogin: { userId: string; timestamp: number };
userLogout: { userId: string };
dataUpdate: { table: string; id: string; data: any };
}
const eventEmitter = new TypedEventEmitter<AppEvents>();
// 类型安全的事件监听
eventEmitter.on('userLogin', (data) => {
// data的类型自动推断为 { userId: string; timestamp: number }
console.log(`User ${data.userId} logged in at ${data.timestamp}`);
});
eventEmitter.emit('userLogin', { userId: '123', timestamp: Date.now() });
条件类型深度应用
条件类型基础
// 基础条件类型
type IsString<T> = T extends string ? true : false;
type Test1 = IsString<string>; // true
type Test2 = IsString<number>; // false
// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type StringOrNumberArray = ToArray<string | number>; // string[] | number[]
// 排除类型
type Exclude<T, U> = T extends U ? never : T;
type Extract<T, U> = T extends U ? T : never;
type WithoutString = Exclude<string | number | boolean, string>; // number | boolean
type OnlyString = Extract<string | number | boolean, string>; // string
// 函数类型条件判断
type IsFunction<T> = T extends (...args: any[]) => any ? true : false;
type Test3 = IsFunction<() => void>; // true
type Test4 = IsFunction<string>; // false
// 获取函数返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type FuncReturn = ReturnType<() => string>; // string
type AsyncFuncReturn = ReturnType<() => Promise<number>>; // Promise<number>
// 获取函数参数类型
type Parameters<T> = T extends (...args: infer P) => any ? P : never;
type FuncParams = Parameters<(a: string, b: number) => void>; // [string, number]
// 获取构造函数实例类型
type InstanceType<T> = T extends new (...args: any[]) => infer R ? R : never;
class MyClass {
value: string = '';
}
type MyInstance = InstanceType<typeof MyClass>; // MyClass
// 深度条件类型
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
interface Config {
database: {
host: string;
port: number;
credentials: {
username: string;
password: string;
};
};
cache: {
enabled: boolean;
ttl: number;
};
}
type PartialConfig = DeepPartial<Config>;
// 所有属性都变为可选,包括嵌套对象
// 条件类型与映射类型结合
type PickByType<T, U> = {
[P in keyof T as T[P] extends U ? P : never]: T[P];
};
interface Person {
name: string;
age: number;
isActive: boolean;
hobbies: string[];
}
type StringProps = PickByType<Person, string>; // { name: string }
type NumberProps = PickByType<Person, number>; // { age: number }
type ArrayProps = PickByType<Person, any[]>; // { hobbies: string[] }
高级条件类型模式
// 递归条件类型
type Flatten<T> = T extends (infer U)[]
? U extends (infer V)[]
? Flatten<V[]>
: U
: T;
type NestedArray = number[][][];
type FlatType = Flatten<NestedArray>; // number
// 字符串模板条件类型
type StartsWith<T extends string, U extends string> = T extends `${U}${string}` ? true : false;
type Test5 = StartsWith<'hello world', 'hello'>; // true
type Test6 = StartsWith<'hello world', 'world'>; // false
// 路径类型提取
type PathKeys<T> = T extends object
? {
[K in keyof T]: K extends string
? T[K] extends object
? `${K}` | `${K}.${PathKeys<T[K]>}`
: `${K}`
: never;
}[keyof T]
: never;
interface NestedObject {
user: {
profile: {
name: string;
age: number;
};
settings: {
theme: string;
};
};
app: {
version: string;
};
}
type Paths = PathKeys<NestedObject>;
// "user" | "app" | "user.profile" | "user.settings" | "user.profile.name" | "user.profile.age" | "user.settings.theme" | "app.version"
// 根据路径获取值类型
type GetByPath<T, P extends string> = P extends keyof T
? T[P]
: P extends `${infer K}.${infer Rest}`
? K extends keyof T
? GetByPath<T[K], Rest>
: never
: never;
type UserName = GetByPath<NestedObject, 'user.profile.name'>; // string
type AppVersion = GetByPath<NestedObject, 'app.version'>; // string
// 类型安全的深度访问函数
function getByPath<T, P extends PathKeys<T>>(
obj: T,
path: P
): GetByPath<T, P> {
const keys = path.split('.');
let result: any = obj;
for (const key of keys) {
result = result[key];
}
return result;
}
const nestedObj: NestedObject = {
user: {
profile: { name: 'Alice', age: 30 },
settings: { theme: 'dark' }
},
app: { version: '1.0.0' }
};
const userName = getByPath(nestedObj, 'user.profile.name'); // string类型,值为'Alice'
const theme = getByPath(nestedObj, 'user.settings.theme'); // string类型,值为'dark'
// 函数管道类型
type Pipe<T extends readonly any[]> = T extends readonly [
(...args: any[]) => infer R,
...infer Rest
]
? Rest extends readonly [(arg: R) => any, ...any[]]
? Pipe<Rest>
: Rest extends readonly []
? R
: never
: never;
// 管道函数实现
function pipe<T extends readonly [(...args: any[]) => any, ...any[]]>(
...fns: T
): (...args: Parameters<T[0]>) => Pipe<T> {
return (...args) => fns.reduce((acc, fn) => fn(acc), fns[0](...args));
}
// 使用示例
const add = (x: number) => x + 1;
const multiply = (x: number) => x * 2;
const toString = (x: number) => x.toString();
const pipeline = pipe(add, multiply, toString);
const result = pipeline(5); // string类型,值为'12'
// 对象键值转换
type KeyValueSwap<T extends Record<string, string | number | symbol>> = {
[K in keyof T as T[K] extends string | number | symbol ? T[K] : never]: K;
};
type Colors = {
red: '#ff0000';
green: '#00ff00';
blue: '#0000ff';
};
type ColorCodes = KeyValueSwap<Colors>;
// { '#ff0000': 'red'; '#00ff00': 'green'; '#0000ff': 'blue' }
// 联合类型转交集类型
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type Union = { a: string } | { b: number } | { c: boolean };
type Intersection = UnionToIntersection<Union>; // { a: string } & { b: number } & { c: boolean }
映射类型与模板字面量
映射类型高级应用
// 基础映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 条件映射类型
type NonFunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
class Example {
name: string = '';
age: number = 0;
getName(): string { return this.name; }
setAge(age: number): void { this.age = age; }
}
type ExampleData = NonFunctionProperties<Example>; // { name: string; age: number }
// 属性修饰符映射
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
type Required<T> = {
[P in keyof T]-?: T[P];
};
interface ReadonlyPartialUser {
readonly name?: string;
readonly age?: number;
}
type MutableRequiredUser = Required<Mutable<ReadonlyPartialUser>>;
// { name: string; age: number }
// 键名转换映射
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type Setters<T> = {
[K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
};
interface User {
name: string;
age: number;
}
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }
type UserSetters = Setters<User>;
// { setName: (value: string) => void; setAge: (value: number) => void }
// 组合映射类型
type GettersAndSetters<T> = Getters<T> & Setters<T>;
type UserAccessors = GettersAndSetters<User>;
// { getName: () => string; getAge: () => number; setName: (value: string) => void; setAge: (value: number) => void }
// 实现自动生成访问器的类
function createAccessors<T extends Record<string, any>>(
data: T
): T & GettersAndSetters<T> {
const result = { ...data } as any;
for (const key in data) {
const capitalizedKey = key.charAt(0).toUpperCase() + key.slice(1);
// 生成getter
result[`get${capitalizedKey}`] = () => result[key];
// 生成setter
result[`set${capitalizedKey}`] = (value: any) => {
result[key] = value;
};
}
return result;
}
const userWithAccessors = createAccessors({ name: 'Alice', age: 30 });
console.log(userWithAccessors.getName()); // 'Alice'
userWithAccessors.setAge(31);
console.log(userWithAccessors.age); // 31
// 深度映射类型
type DeepMutable<T> = {
-readonly [P in keyof T]: T[P] extends object ? DeepMutable<T[P]> : T[P];
};
type DeepRequired<T> = {
[P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};
interface DeepReadonlyPartial {
readonly user?: {
readonly profile?: {
readonly name?: string;
readonly age?: number;
};
};
}
type DeepMutableRequired = DeepRequired<DeepMutable<DeepReadonlyPartial>>;
// { user: { profile: { name: string; age: number } } }
模板字面量类型
// 基础模板字面量类型
type Greeting = `Hello, ${string}!`;
const greeting1: Greeting = 'Hello, World!'; // ✓
const greeting2: Greeting = 'Hello, TypeScript!'; // ✓
// const greeting3: Greeting = 'Hi, World!'; // ✗
// 联合类型模板
type Color = 'red' | 'green' | 'blue';
type Size = 'small' | 'medium' | 'large';
type ColoredSize = `${Color}-${Size}`;
// 'red-small' | 'red-medium' | 'red-large' | 'green-small' | ... | 'blue-large'
// 递归模板类型
type Join<T extends readonly string[], D extends string = ','>
= T extends readonly [infer F, ...infer R]
? F extends string
? R extends readonly string[]
? R['length'] extends 0
? F
: `${F}${D}${Join<R, D>}`
: never
: never
: '';
type JoinedColors = Join<['red', 'green', 'blue'], '-'>; // 'red-green-blue'
type CsvHeader = Join<['name', 'age', 'email']>; // 'name,age,email'
// 字符串操作类型
type Split<S extends string, D extends string> =
S extends `${infer T}${D}${infer U}`
? [T, ...Split<U, D>]
: [S];
type SplitPath = Split<'user.profile.name', '.'>; // ['user', 'profile', 'name']
// 驼峰命名转换
type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
? `${P1}${Uppercase<P2>}${CamelCase<P3>}`
: S;
type CamelCased = CamelCase<'user_profile_name'>; // 'userProfileName'
// 蛇形命名转换
type SnakeCase<S extends string> = S extends `${infer T}${infer U}`
? `${T extends Capitalize<T> ? '_' : ''}${Lowercase<T>}${SnakeCase<U>}`
: S;
type SnakeCased = SnakeCase<'UserProfileName'>; // '_user_profile_name'
// URL路径类型
type Route = '/users' | '/users/:id' | '/posts' | '/posts/:id/comments';
type ExtractParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}`
? { [K in Param]: string } & ExtractParams<`/${Rest}`>
: T extends `${string}:${infer Param}`
? { [K in Param]: string }
: {};
type UserRouteParams = ExtractParams<'/users/:id'>; // { id: string }
type CommentRouteParams = ExtractParams<'/posts/:id/comments'>; // { id: string }
// 类型安全的路由函数
function createRoute<T extends string>(
path: T
): (params: ExtractParams<T>) => string {
return (params) => {
let result = path;
for (const [key, value] of Object.entries(params)) {
result = result.replace(`:${key}`, value);
}
return result;
};
}
const userRoute = createRoute('/users/:id');
const userUrl = userRoute({ id: '123' }); // '/users/123'
const commentRoute = createRoute('/posts/:postId/comments/:commentId');
const commentUrl = commentRoute({ postId: '456', commentId: '789' });
// '/posts/456/comments/789'
实用工具类型
自定义工具类型
// 可选属性工具类型
type OptionalKeys<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? K : never;
}[keyof T];
type RequiredKeys<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
}[keyof T];
interface MixedInterface {
required: string;
optional?: number;
alsoOptional?: boolean;
}
type OptionalProps = OptionalKeys<MixedInterface>; // 'optional' | 'alsoOptional'
type RequiredProps = RequiredKeys<MixedInterface>; // 'required'
// 类型合并工具
type Merge<T, U> = {
[K in keyof T | keyof U]: K extends keyof U
? U[K]
: K extends keyof T
? T[K]
: never;
};
type A = { a: string; b: number };
type B = { b: string; c: boolean };
type Merged = Merge<A, B>; // { a: string; b: string; c: boolean }
// 深度合并类型
type DeepMerge<T, U> = {
[K in keyof T | keyof U]: K extends keyof U
? K extends keyof T
? T[K] extends object
? U[K] extends object
? DeepMerge<T[K], U[K]>
: U[K]
: U[K]
: U[K]
: K extends keyof T
? T[K]
: never;
};
// 数组类型工具
type Head<T extends readonly any[]> = T extends readonly [infer H, ...any[]] ? H : never;
type Tail<T extends readonly any[]> = T extends readonly [any, ...infer R] ? R : [];
type Last<T extends readonly any[]> = T extends readonly [...any[], infer L] ? L : never;
type FirstElement = Head<[1, 2, 3]>; // 1
type RestElements = Tail<[1, 2, 3]>; // [2, 3]
type LastElement = Last<[1, 2, 3]>; // 3
// 元组长度类型
type Length<T extends readonly any[]> = T['length'];
type ArrayLength = Length<[1, 2, 3, 4, 5]>; // 5
// 元组反转类型
type Reverse<T extends readonly any[]> = T extends readonly [...infer Rest, infer Last]
? [Last, ...Reverse<Rest>]
: [];
type Reversed = Reverse<[1, 2, 3, 4]>; // [4, 3, 2, 1]
// 函数组合类型
type Compose<F extends readonly any[]> = F extends readonly [
(...args: any[]) => infer R,
...infer Rest
]
? Rest extends readonly [any, ...any[]]
? Rest extends readonly [(arg: R) => any, ...any[]]
? Compose<Rest>
: never
: R
: never;
// 实现compose函数
function compose<T extends readonly [(...args: any[]) => any, ...any[]]>(
...fns: T
): (...args: Parameters<T[0]>) => Compose<T> {
return (...args) => fns.reduceRight((acc, fn) => fn(acc), fns[0](...args));
}
// Promise工具类型
type PromiseValue<T> = T extends Promise<infer U> ? U : T;
type PromiseValues<T extends readonly any[]> = {
[K in keyof T]: PromiseValue<T[K]>;
};
type SinglePromise = PromiseValue<Promise<string>>; // string
type MultiplePromises = PromiseValues<[Promise<string>, Promise<number>, boolean]>;
// [string, number, boolean]
// 异步函数类型工具
type AsyncReturnType<T extends (...args: any[]) => Promise<any>> =
T extends (...args: any[]) => Promise<infer R> ? R : never;
async function fetchUser(): Promise<{ id: number; name: string }> {
return { id: 1, name: 'Alice' };
}
type UserType = AsyncReturnType<typeof fetchUser>; // { id: number; name: string }
// 类型守卫工具
type TypeGuard<T> = (value: any) => value is T;
function createTypeGuard<T>(validator: (value: any) => boolean): TypeGuard<T> {
return (value: any): value is T => validator(value);
}
const isString = createTypeGuard<string>(value => typeof value === 'string');
const isNumber = createTypeGuard<number>(value => typeof value === 'number');
function processValue(value: unknown) {
if (isString(value)) {
// value的类型现在是string
console.log(value.toUpperCase());
} else if (isNumber(value)) {
// value的类型现在是number
console.log(value.toFixed(2));
}
}
总结
TypeScript高级类型的核心要点:
- 泛型约束:使用extends关键字限制泛型类型
- 条件类型:基于类型条件进行类型推断和转换
- 映射类型:遍历和转换对象类型的属性
- 模板字面量:类型级别的字符串操作和模式匹配
- 工具类型:构建可复用的类型操作工具
掌握这些高级类型模式能够让我们编写更加类型安全、可维护的TypeScript代码,充分发挥TypeScript类型系统的威力。