阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 自定义类型声明

自定义类型声明

作者:陈川 阅读数:36199人阅读 分类: TypeScript

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
  }
}

typeofinstanceofin 操作符都可以作为类型守卫:

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

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌