首页 > 解决方案 > 在 Typescript 中使用装饰器模式时如何使参数的类型保持一致

问题描述

我有几个需要访问数据库的功能。

const dbProcess1 = (s1: string) => {
    console.log(`dbProcess1 is called with a param : ${s1}`)
};

const dbProcess2 = (s2: string, n2: number) => {
    console.log(`dbProcess2 is called with params : ${s2}, ${n2}`)
};

const dbProcess3 = (s1: string, s2: string, n2: number) => {
    dbProcess1(s1);
    dbProcess2(s2, n2);
};

我想在这些过程之前和之后控制微调器。以下装饰器是我的方法。

const withSpinner = (process: (...params: any[]) => void) => {
    return (...params: any[]) => {
        console.log('display spinner');
        process(...params);
        console.log('stop spinner');
    }
};

const dbProcess1WithSpinner = withSpinner(dbProcess1);
const dbProcess2WithSpinner = withSpinner(dbProcess2);
const dbProcess3WithSpinner = withSpinner(dbProcess3);

dbProcess1WithSpinner('p1');
dbProcess2WithSpinner('p2','42');
dbProcess3WithSpinner('p1', 'p2', '42');

但是,这种方法使类型提示无用:

const dbProcess3: (s1: string, s2: string, n2: number) => void

变成

const dbProcess3WithSpinner: (...params: any[]) => void

有什么建议可以让它变得更好吗?

标签: typescriptdecorator

解决方案


您可以使用一些泛型来修复类型:

declare function dbProcess3(s1: string, s2: string, n2: number): void;

const withSpinner = <T extends (...args: any[]) => any>(process: T) => {
    return (...params: Parameters<T>) => {
        console.log('display spinner');
        process(...params);
        console.log('stop spinner');
    }
};

const dbProcess3WithSpinner = withSpinner(dbProcess3); // is now (s1: string, s2: string, n2: number) => void

dbProcess3WithSpinner('p1', 'p2', '42'); // error: Argument of type '"42"' is not assignable to parameter of type 'number'

现在装饰器参数已经过正确的类型检查(它只接受与装饰函数期望获得的相同的参数集)。

使用参数实用程序提取函数参数类型

操场


推荐阅读