自定义类型声明
TypeScript 的自定义类型声明是增强代码可读性和维护性的核心工具。通过类型别名、接口、联合类型等机制,开发者能够精确描述数据结构,约束变量形态,甚至扩展第三方库的类型定义。
类型别名与基础声明
类型别名(type
)允许为复杂类型创建简短的名称。它支持原始类型、联合类型、元组等任何有效的 TypeScript 类型:
type UserID = string | number; // 联合类型
type Point = [number, number]; // 元组类型
type Callback<T> = (data: T) => void; // 泛型函数类型
与接口不同,类型别名可以直接定义联合类型或使用模板字面量类型:
type Status = 'active' | 'inactive'; // 字面量联合
type EventName = `${'click' | 'hover'}_${'menu' | 'button'}`; // 模板字面量
接口的深度应用
接口(interface
)特别适合描述对象结构,支持继承、合并声明等特性:
interface User {
id: number;
name: string;
readonly registerDate: Date; // 只读属性
}
// 接口继承
interface Admin extends User {
permissions: string[];
}
// 声明合并
interface User {
email?: string; // 可选属性
}
通过索引签名可以定义动态属性:
interface StringMap {
[key: string]: string; // 任意字符串属性
}
联合与交叉类型实战
联合类型(|
)表示"或"关系,交叉类型(&
)表示"与"关系:
type NetworkState =
| { status: 'loading' }
| { status: 'success', data: string }
| { status: 'error', code: number };
type Draggable = {
drag: () => void
};
type Resizable = {
resize: () => void
};
type UIWidget = Draggable & Resizable;
类型守卫与类型推断
通过类型守卫可以缩小联合类型的范围:
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function process(input: string | number) {
if (isString(input)) {
input.toUpperCase(); // 类型被推断为string
}
}
typeof
、instanceof
、in
操作符都可以作为类型守卫:
class Bird {
fly() {}
}
class Fish {
swim() {}
}
function move(pet: Bird | Fish) {
if (pet instanceof Bird) {
pet.fly();
} else {
pet.swim();
}
}
泛型约束与高级模式
泛型可以结合约束条件实现灵活的类型控制:
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(arg: T): T {
console.log(arg.length);
return arg;
}
// 条件类型示例
type Flatten<T> = T extends Array<infer U> ? U : T;
type Nested = Array<string>;
type Flat = Flatten<Nested>; // string
映射类型可以批量转换属性:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
声明文件与模块扩展
为第三方库添加类型声明:
// globals.d.ts
declare module '*.svg' {
const content: string;
export default content;
}
// 扩展现有模块
declare module 'axios' {
interface AxiosRequestConfig {
retry?: number;
}
}
环境声明允许描述非TypeScript代码:
declare const __VERSION__: string;
declare function showToast(message: string): void;
实用工具类型解析
TypeScript 内置了多种工具类型:
interface Todo {
title: string;
description: string;
completed: boolean;
}
// 构造新类型
type TodoPreview = Pick<Todo, 'title' | 'completed'>;
type TodoInfo = Omit<Todo, 'completed'>;
// 修改属性
type ReadonlyTodo = Readonly<Todo>;
type PartialTodo = Partial<Todo>;
自定义工具类型示例:
type Nullable<T> = T | null;
type ValueOf<T> = T[keyof T];
type AsyncReturnType<T> = T extends (...args: any[]) => Promise<infer R> ? R : never;
类型兼容性与结构子类型
TypeScript 使用结构类型系统:
interface Named {
name: string;
}
class Person {
constructor(public name: string) {}
}
let p: Named;
p = new Person('Alice'); // 兼容,因为结构匹配
函数参数兼容性采用双向协变:
type Handler = (event: Event) => void;
const clickHandler: Handler = (e: MouseEvent) => {}; // 允许
const genericHandler = (e: Event) => {};
const mouseHandler: (e: MouseEvent) => void = genericHandler; // 也允许
装饰器与反射元数据
结合装饰器实现类型元编程:
import 'reflect-metadata';
function validate(target: any, key: string) {
const type = Reflect.getMetadata('design:type', target, key);
console.log(`${key} type: ${type.name}`);
}
class User {
@validate
name: string; // 输出: name type: String
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn