关于 TypeScript 装饰器和接口的问题,请教一下各位 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
DreamingCTW
V2EX    TypeScript

关于 TypeScript 装饰器和接口的问题,请教一下各位

  •  
  •   DreamingCTW 192 天前 1990 次点击
    这是一个创建于 192 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我是做 Java 后端的,这两天正在系统化的学习 ts ,学到装饰器的时候,有点疑惑,希望可以指导下,谢谢大家。以下是 Demo

    如果不声明 interface Person { getCreateTime(): void },那么 person.getCreateTime()会报错,提示 Person 对象中没有这个属性。加上这个接口就不会报错了,但有一个问题,接口中规范了 getCreateTime()函数的返回值为 void ,实际上装饰器中 getCreateTime()返回的是 string ,这不矛盾吗?我尝试修改接口中的 getCreateTime()函数的返回值,发现改成任意类型都可以...

    现在给我的感觉就是,为了让 person.getCreateTime()代码不报错,就打了 interface Person 这个补丁,而且可以不强制遵循这个补丁的规范。

    由此我想到了另一个问题,从上述代码看,Person 既是一个 class ,也是一个 interface ,我还可以创建一个新的 class 来 implements Person ,发现 class Person 中的所有属性也都要实现,所以 interface Person 是把 class Person 转成了接口?

    class NewPerson implements Person { name: string; age: number; createTime: Date; constructor(name: string, age: number) { this.name = name; this.age = age; this.createTime = new Date(); } getCreateTime() { return `该对象的创建时间是:${this.createTime}`; } } 
    9 条回复    2025-04-03 16:49:19 +08:00
    X0V0X
        1
    X0V0X  
       192 天前
    这就是人们说的 java 味吗
    FrankFang128
        2
    FrankFang128  
       192 天前
    大部分 JSer 不用装饰器
    jackge0323
        3
    jackge0323  
       192 天前
    这部分可以跳过,基本不用。
    linkopeneyes
        4
    linkopeneyes  
       192 天前
    这种情况还是继承比较好,当然类装饰器也可以规定类长什么样子,这样就可以要求强制继承一个带这个方法的类了
    lisongeee
        5
    lisongeee  
       192 天前   1
    ts 认为装饰器不会改变类型,因此你声明的时候类型是啥它就是啥

    达到你想要的效果也很简单,将声明改为调用

    const Person = LogTime(
    class {
    name: string;
    age: number;
    constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
    }
    },
    );
    lanten
        6
    lanten  
       192 天前
    目前再 TS 中的任何装饰器(类/方法/属性/参数装饰器)都无法更改调用该装饰器目标的原始类型.

    由于你的 getCreateTime 方法是在装饰器中添加的, 且在原始类(Person)中没有该方法的签名, 所以 person 实例在类型系统中压根没有 getCreateTime 方法, 报错符合预期.

    声明 `interface Person` 是不完美的, 这会破坏类型系统的准确性. (但也不是不行)

    我个人认为你这种场景应该使用基类派生(extends), 而不是装饰器, 通常类装饰器需要配合方法装饰器或属性装饰器才能体现其价值
    DreamingCTW
        7
    DreamingCTW  
    OP
       192 天前
    @lanten #6 我是在哔站看的 ts 视频,里面讲装饰器的时候举的这个例子,当他为了解决 person 中没有 getCreateTime 函数时,就用了 interface ,他用的时候我没觉得有问题,但当他写 getCreateTime 时,声明了 void ,我就发现了这个问题。他假设的场景是,为每一个 class 的实例对象创建时都记录一个创建时间,所以用了装饰器,这样可以很方便的为每一个 class 上写 @LogTime
    DreamingCTW
        8
    DreamingCTW  
    OP
       192 天前
    @sjhhjx0122 #4 他假设的场景是,为每一个 class 的实例对象创建时都记录一个创建时间,所以用了装饰器,这样可以很方便的为每一个 class 上写 @LogTime ,只是我在学习的过程中发现了有这个问题。
    sillydaddy
        9
    sillydaddy  
       192 天前
    可以给装饰器定义明确的返回类型:

    ```
    interface WithCreateTime {
    getCreateTime(): string;
    }

    function LogTime<T extends Constructor>(Base: T): T & Constructor<WithCreateTime>;
    ```

    上面的 LogTime 函数定义中,明确指定了返回类型:T & Constructor<WithCreateTime> 。并且与 LogTime 实际返回值的类型是一致的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1375 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 16:39 PVG 00:39 LAX 09:39 JFK 12:39
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86