TypeScript any与unknown #
一、any类型 #
1.1 什么是any #
any类型是TypeScript的特殊类型,表示任意类型。使用any会跳过类型检查。
typescript
let anything: any = 'hello';
anything = 123;
anything = true;
anything = {};
anything = [];
1.2 any的特点 #
- 可以赋值给任何类型
- 可以调用任何方法
- 可以访问任何属性
- 编译器不进行类型检查
typescript
let value: any = 'hello';
value.toUpperCase();
value.toFixed();
value.nonExistentMethod();
value.foo.bar.baz;
1.3 any的使用场景 #
与JavaScript代码交互 #
typescript
declare const legacyLibrary: any;
legacyLibrary.doSomething();
legacyLibrary.configure({ option: true });
快速原型开发 #
typescript
function processData(data: any): any {
return data.transform();
}
逐步迁移JavaScript代码 #
typescript
let data: any = JSON.parse(jsonString);
console.log(data.user.name);
1.4 any的风险 #
typescript
let value: any = 'hello';
let num: number = value;
num.toFixed(2);
1.5 隐式any #
在严格模式下,未指定类型的变量会报错:
typescript
function add(a, b) {
return a + b;
}
需要显式指定类型:
typescript
function add(a: number, b: number): number {
return a + b;
}
二、unknown类型 #
2.1 什么是unknown #
unknown是TypeScript 3.0引入的类型安全的any。它表示未知类型,但在使用前必须进行类型检查。
typescript
let value: unknown = 'hello';
value.toUpperCase();
2.2 unknown的特点 #
- 可以赋值任何类型的值
- 不能直接赋值给其他类型
- 不能直接调用方法
- 必须先进行类型检查
typescript
let value: unknown = 'hello';
let str: string = value;
if (typeof value === 'string') {
let str: string = value;
console.log(str.toUpperCase());
}
2.3 类型收窄 #
typescript
function process(value: unknown): void {
if (typeof value === 'string') {
console.log(value.toUpperCase());
} else if (typeof value === 'number') {
console.log(value.toFixed(2));
} else if (Array.isArray(value)) {
console.log(value.length);
} else if (typeof value === 'object' && value !== null) {
console.log(Object.keys(value));
} else {
console.log('Unknown type');
}
}
2.4 类型断言 #
typescript
let value: unknown = 'hello';
let str = value as string;
console.log(str.toUpperCase());
2.5 自定义类型守卫 #
typescript
interface User {
name: string;
age: number;
}
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'name' in value &&
'age' in value &&
typeof (value as User).name === 'string' &&
typeof (value as User).age === 'number'
);
}
function greet(value: unknown): void {
if (isUser(value)) {
console.log(`Hello, ${value.name}!`);
} else {
console.log('Invalid user');
}
}
三、any vs unknown #
3.1 类型安全对比 #
typescript
let anyValue: any = 'hello';
let unknownValue: unknown = 'hello';
anyValue.toUpperCase();
unknownValue.toUpperCase();
if (typeof unknownValue === 'string') {
unknownValue.toUpperCase();
}
3.2 赋值对比 #
typescript
let anyValue: any = 'hello';
let unknownValue: unknown = 'hello';
let str1: string = anyValue;
let str2: string = unknownValue;
if (typeof unknownValue === 'string') {
let str2: string = unknownValue;
}
3.3 方法调用对比 #
typescript
let anyValue: any = { name: 'TypeScript' };
let unknownValue: unknown = { name: 'TypeScript' };
anyValue.toUpperCase();
anyValue.name;
anyValue.foo.bar;
unknownValue.toUpperCase();
unknownValue.name;
3.4 对比总结 #
| 特性 | any | unknown |
|---|---|---|
| 类型安全 | 不安全 | 安全 |
| 可以赋值任何类型 | 是 | 是 |
| 可以赋值给其他类型 | 是 | 否(需要检查) |
| 可以调用任何方法 | 是 | 否(需要检查) |
| 类型检查 | 跳过 | 需要 |
四、最佳实践 #
4.1 避免使用any #
typescript
function process(data: any): any {
return data.value;
}
function process<T>(data: { value: T }): T {
return data.value;
}
4.2 使用unknown替代any #
typescript
function parseJSON(json: string): unknown {
return JSON.parse(json);
}
const data = parseJSON('{"name": "TypeScript"}');
if (typeof data === 'object' && data !== null && 'name' in data) {
console.log((data as { name: string }).name);
}
4.3 使用类型守卫 #
typescript
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function isNumber(value: unknown): value is number {
return typeof value === 'number';
}
function process(value: unknown): void {
if (isString(value)) {
console.log(value.toUpperCase());
} else if (isNumber(value)) {
console.log(value.toFixed(2));
}
}
4.4 使用泛型 #
typescript
function identity<T>(value: T): T {
return value;
}
const str = identity('hello');
const num = identity(42);
五、实用示例 #
5.1 API响应处理 #
typescript
interface ApiResponse<T> {
code: number;
message: string;
data: T;
}
async function fetchData<T>(url: string): Promise<T> {
const response = await fetch(url);
const data: unknown = await response.json();
if (isValidResponse<T>(data)) {
return data.data;
}
throw new Error('Invalid response format');
}
function isValidResponse<T>(value: unknown): value is ApiResponse<T> {
return (
typeof value === 'object' &&
value !== null &&
'code' in value &&
'message' in value &&
'data' in value
);
}
5.2 JSON解析 #
typescript
function safeParse<T>(json: string, validator: (value: unknown) => value is T): T | null {
try {
const data: unknown = JSON.parse(json);
return validator(data) ? data : null;
} catch {
return null;
}
}
interface User {
name: string;
age: number;
}
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'name' in value &&
'age' in value
);
}
const user = safeParse<User>('{"name":"Alice","age":25}', isUser);
5.3 类型安全的Object.keys #
typescript
function getKeys<T extends object>(obj: T): (keyof T)[] {
return Object.keys(obj) as (keyof T)[];
}
const user = {
name: 'Alice',
age: 25
};
const keys = getKeys(user);
5.4 类型安全的属性访问 #
typescript
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = {
name: 'Alice',
age: 25
};
const name = getProperty(user, 'name');
const age = getProperty(user, 'age');
六、类型断言技巧 #
6.1 非空断言 #
typescript
let value: string | null = 'hello';
let length: number = value!.length;
6.2 双重断言 #
typescript
let value: unknown = 'hello';
let num: number = value as unknown as number;
6.3 const断言 #
typescript
let value = 'hello' as const;
let arr = [1, 2, 3] as const;
let obj = { name: 'Alice' } as const;
七、总结 #
本章介绍了TypeScript的any和unknown类型:
any类型 #
- 表示任意类型
- 跳过类型检查
- 不安全,容易引入错误
- 仅在必要时使用
unknown类型 #
- 类型安全的any
- 使用前必须进行类型检查
- 推荐替代any
- 更好的类型安全
最佳实践 #
- 尽量避免使用any
- 使用unknown替代any
- 使用类型守卫进行类型收窄
- 使用泛型提高类型安全性
- 使用类型断言时确保安全
最后更新:2026-03-26