typeof类型操作符
typeof类型操作符的基本概念
typeof
是TypeScript中一个重要的类型操作符,它可以在类型上下文中使用来获取变量或属性的类型。这个操作符与JavaScript中的typeof
运算符虽然写法相同,但功能完全不同。在类型位置使用时,它会返回一个表示给定变量类型的类型值。
let str = "hello";
type StrType = typeof str; // string
const num = 42;
type NumType = typeof num; // 42 (字面量类型)
typeof与变量声明
当对变量使用typeof
时,它会捕获该变量的声明类型。对于使用let
或var
声明的变量,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的类型推断规则,但有一些特殊行为需要注意:
- 对于
const
声明的对象字面量,typeof
会保留所有属性的字面量类型 - 对于数组字面量,
typeof
会推断出数组元素的联合类型 - 对于函数表达式,
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
常与keyof
、in
等操作符一起使用:
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
功能强大,但也有一些限制:
- 不能用于获取运行时值的动态类型
- 对于函数重载,
typeof
只会捕获最后一个重载签名 - 在全局作用域中,
typeof
不能用于未声明的变量
declare function fn(x: string): number;
declare function fn(x: number): string;
type FnType = typeof fn; // (x: number) => string,只捕获最后一个重载
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn