阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > typeof类型操作符

typeof类型操作符

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

typeof类型操作符的基本概念

typeof是TypeScript中一个重要的类型操作符,它可以在类型上下文中使用来获取变量或属性的类型。这个操作符与JavaScript中的typeof运算符虽然写法相同,但功能完全不同。在类型位置使用时,它会返回一个表示给定变量类型的类型值。

let str = "hello";
type StrType = typeof str;  // string

const num = 42;
type NumType = typeof num;  // 42 (字面量类型)

typeof与变量声明

当对变量使用typeof时,它会捕获该变量的声明类型。对于使用letvar声明的变量,typeof会得到变量的类型注解(如果没有显式注解,则是推断出的类型)。而对于const声明的原始类型变量,typeof会得到字面量类型。

let x = 10;         // x的类型是number
type X = typeof x;  // number

const y = 10;       // y的类型是10
type Y = typeof y;  // 10

typeof与对象和数组

对于对象和数组这样的复杂类型,typeof会完整地捕获它们的结构类型:

const person = {
  name: "Alice",
  age: 30,
  hobbies: ["reading", "swimming"]
};

type Person = typeof person;
/* 等价于:
type Person = {
  name: string;
  age: number;
  hobbies: string[];
}
*/

const numbers = [1, 2, 3];
type Numbers = typeof numbers;  // number[]

typeof与函数

typeof也可以用于捕获函数的类型签名,包括参数类型和返回值类型:

function greet(name: string): string {
  return `Hello, ${name}!`;
}

type GreetFn = typeof greet;
/* 等价于:
type GreetFn = (name: string) => string;
*/

typeof在类型守卫中的应用

typeof类型操作符可以与类型守卫结合使用,帮助缩小类型范围:

function padLeft(value: string | number, padding: string | number) {
  if (typeof value === "number") {
    // 这里value的类型被缩小为number
    return Array(value + 1).join(" ") + padding;
  }
  // 这里value的类型是string
  return padding + value;
}

typeof与枚举

当应用于枚举时,typeof会得到枚举的类型表示:

enum Direction {
  Up,
  Down,
  Left,
  Right
}

type DirectionType = typeof Direction;
/* 
等价于:
type DirectionType = {
  Up: Direction.Up;
  Down: Direction.Down;
  Left: Direction.Left;
  Right: Direction.Right;
}
*/

typeof与类

对于类,typeof会获取类的构造函数类型,而不是实例类型:

class Person {
  constructor(public name: string) {}
}

type PersonConstructor = typeof Person;
/* 
等价于:
type PersonConstructor = new (name: string) => Person
*/

const createPerson = (ctor: PersonConstructor, name: string) => {
  return new ctor(name);
};

typeof与模块

在模块系统中,typeof可以用来获取导入模块的类型:

// 假设有一个模块config.ts
export const config = {
  apiUrl: "https://api.example.com",
  timeout: 5000
};

// 在另一个文件中
import { config } from "./config";

type AppConfig = typeof config;
/* 
等价于:
type AppConfig = {
  apiUrl: string;
  timeout: number;
}
*/

typeof的类型推断行为

typeof的类型推断遵循TypeScript的类型推断规则,但有一些特殊行为需要注意:

  1. 对于const声明的对象字面量,typeof会保留所有属性的字面量类型
  2. 对于数组字面量,typeof会推断出数组元素的联合类型
  3. 对于函数表达式,typeof会捕获完整的函数签名
const obj = {
  id: 123,       // number
  name: "test"   // string
} as const;      // 使用as const后所有属性变为字面量类型

type ObjType = typeof obj;
/* 
等价于:
type ObjType = {
  readonly id: 123;
  readonly name: "test";
}
*/

typeof与模板字符串

typeof也可以与模板字符串类型一起使用:

const eventName = "click";
type EventHandlerName = `on${typeof eventName}`;  // "onclick"

const colors = ["red", "green", "blue"] as const;
type ColorVariants = `${typeof colors[number]}-variant`;  // "red-variant" | "green-variant" | "blue-variant"

typeof的嵌套使用

typeof可以嵌套使用来获取更深层次的类型信息:

const apiResponse = {
  data: {
    users: [
      { id: 1, name: "Alice" },
      { id: 2, name: "Bob" }
    ]
  }
};

type User = typeof apiResponse["data"]["users"][number];
/* 
等价于:
type User = {
  id: number;
  name: string;
}
*/

typeof与泛型

typeof可以与泛型结合使用,创建更灵活的类型操作:

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

const user = { name: "Alice", age: 30 };
type AgeType = typeof user["age"];  // number

const age = getProperty(user, "age");  // 类型为number

typeof在高级类型中的应用

在更复杂的类型操作中,typeof常与keyofin等操作符一起使用:

const formFields = {
  username: "",
  password: "",
  rememberMe: false
};

type FormFieldKeys = keyof typeof formFields;  // "username" | "password" | "rememberMe"
type FormFieldValues = typeof formFields[FormFieldKeys];  // string | boolean

type FormValidator = {
  [K in keyof typeof formFields]: (value: typeof formFields[K]) => boolean;
};
/* 
等价于:
type FormValidator = {
  username: (value: string) => boolean;
  password: (value: string) => boolean;
  rememberMe: (value: boolean) => boolean;
}
*/

typeof与类型查询

typeof本质上是一种类型查询操作,它允许我们在类型位置引用值的类型。这种能力在需要保持类型同步时特别有用:

// 运行时值
const defaultConfig = {
  port: 3000,
  env: "development",
  debug: true
};

// 类型与值保持同步
type AppConfig = typeof defaultConfig;

function loadConfig(override: Partial<AppConfig>): AppConfig {
  return { ...defaultConfig, ...override };
}

typeof与映射类型

结合映射类型,typeof可以用于创建基于现有对象结构的派生类型:

const settings = {
  theme: "dark",
  fontSize: 14,
  autoSave: true
};

type SettingsOptions = {
  [K in keyof typeof settings]: Array<typeof settings[K]>;
};
/* 
等价于:
type SettingsOptions = {
  theme: string[];
  fontSize: number[];
  autoSave: boolean[];
}
*/

typeof的局限性

虽然typeof功能强大,但也有一些限制:

  1. 不能用于获取运行时值的动态类型
  2. 对于函数重载,typeof只会捕获最后一个重载签名
  3. 在全局作用域中,typeof不能用于未声明的变量
declare function fn(x: string): number;
declare function fn(x: number): string;

type FnType = typeof fn;  // (x: number) => string,只捕获最后一个重载

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:keyof操作符

下一篇:索引访问类型

前端川

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