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
  • 更好的类型安全

最佳实践 #

  1. 尽量避免使用any
  2. 使用unknown替代any
  3. 使用类型守卫进行类型收窄
  4. 使用泛型提高类型安全性
  5. 使用类型断言时确保安全
最后更新:2026-03-26