MST
星途 面试题库

面试题:TypeScript 类型别名 type 在复杂泛型场景下的应用

设计一个使用类型别名 type 配合泛型的复杂场景,例如创建一个通用的缓存函数,它可以缓存不同类型函数的返回值,要求通过类型别名 type 精确控制缓存函数的输入输出类型,以及处理缓存命中和未命中的逻辑,并对代码中的类型别名设计进行详细解释。
26.5万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
// 定义一个类型别名,用于表示缓存函数的返回值
// 这里的泛型 T 表示原始函数的返回值类型
type CacheResult<T> = {
    value: T;
    timestamp: number;
};

// 定义一个类型别名,用于表示缓存对象
// 这里的泛型 F 表示原始函数类型,通过 Parameters<F> 获取函数参数类型,ReturnType<F> 获取函数返回值类型
type Cache<F extends (...args: any[]) => any> = {
    [key: string]: CacheResult<ReturnType<F>>;
};

// 定义缓存函数,接受一个原始函数作为参数
function createCache<F extends (...args: any[]) => any>(fn: F): (...args: Parameters<F>) => ReturnType<F> {
    const cache: Cache<F> = {};
    return function (...args: Parameters<F>): ReturnType<F> {
        const key = args.toString();
        if (cache[key] && Date.now() - cache[key].timestamp < 1000) { // 缓存命中,假设缓存有效期1秒
            return cache[key].value;
        }
        const result = fn.apply(this, args);
        cache[key] = {
            value: result,
            timestamp: Date.now()
        };
        return result;
    };
}

// 示例函数
function add(a: number, b: number): number {
    return a + b;
}

const cachedAdd = createCache(add);
console.log(cachedAdd(1, 2)); // 第一次调用,计算并缓存
console.log(cachedAdd(1, 2)); // 第二次调用,命中缓存

类型别名设计解释

  1. CacheResult<T>
    • 这个类型别名用于定义缓存结果的结构。T 是一个泛型,代表原始函数的返回值类型。
    • value 属性存储原始函数的返回值。
    • timestamp 属性记录缓存的时间戳,用于判断缓存是否过期。
  2. Cache<F>
    • F 是一个泛型,代表原始函数类型,要求 F 是一个接受任意参数并返回任意类型的函数。
    • 这个类型别名定义了缓存对象的结构,它是一个对象,键是字符串类型(由函数参数生成),值是 CacheResult<ReturnType<F>> 类型,即缓存结果类型,其中 ReturnType<F> 提取了原始函数 F 的返回值类型。
  3. createCache<F>
    • F 同样是代表原始函数类型的泛型。
    • 该函数接受一个类型为 F 的原始函数 fn 作为参数,并返回一个新的函数。
    • 返回的新函数接受与原始函数 fn 相同类型的参数(通过 Parameters<F> 获取),并返回与原始函数 fn 相同类型的返回值(通过 ReturnType<F> 获取)。

通过这些类型别名的设计,精确控制了缓存函数的输入输出类型,以及缓存对象的结构,确保了类型安全和代码的可维护性。