如何让 TypeScript 正确推导计算属性名的引用? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
SilentDepth
V2EX    Javascript

如何让 TypeScript 正确推导计算属性名的引用?

  •  
  •   SilentDepth 2018 年 11 月 3 日 6206 次点击
    这是一个创建于 2660 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如有这么一个类:

    class Something { set (key: string, val: any) { this['set$' + key](val) // 上面这句会有类型错误提示 } set$name (name: string) {...} set$age (age: number) {...} } 

    在启用 noImplicitAny 时 TS 会报错:'Something' has no index signature.(在 this[...] 部分)。然而并不知道如何标注类型。

    key 可能的取值有一个明确的列表,其类型在这里也可以写成 key: 'name' | 'age'。所以虽然这种计算属性名是运行时逻辑,但理论上是可以在编译时分析的(字面量和固定值的计算)。于是问题就是 TS 现在是否支持这种分析?

    PS: 刚注意到 V2EX 还没有 TS 节点。

    第 1 条附言    2018 年 11 月 3 日
    我是想用 TS 实现这段代码的效果:

    https://jsfiddle.net/SilentDepth/3ydpra7q/
    15 条回复    2018-11-04 23:58:55 +08:00
    kernel
        1
    kernel  
       2018 年 11 月 3 日
    不可能的,你把 set$name 方法前的 set$去掉还有一点可能
    des
        2
    des  
       2018 年 11 月 3 日 via Android
    不可能
    SilentDepth
        4
    SilentDepth  
    OP
       2018 年 11 月 3 日
    @vghdjgh #3 Options 里开启 noImplicitAny 后,错误提示出现。
    SilentDepth
        6
    SilentDepth  
    OP
       2018 年 11 月 3 日
    @kcats #5 这是不是和 @ts-ignore 一个效果……

    再尝试搜索了一下,放弃从 TS 寻找原生解决方案了。个人觉得这也算 JS 编码的常见套路,希望 TS 早日能支持这个特性吧。
    buhi
        7
    buhi  
       2018 年 11 月 3 日
    这个虽然是 js 编码的常见套路, 但是不能称得上一个好套路, 所以不支持也无可厚非.
    如果改成这样那就可以支持
    ```
    type Properties = {
    name:string,
    age:number
    }
    class Foo {
    set<k extends keyof Properties>(key:k, value: Properties[k]){
    this.properties[key] = value
    }
    properties:Properties
    }
    const f = new Foo()
    f.set("name",233) //报错
    ```
    SilentDepth
        8
    SilentDepth  
    OP
       2018 年 11 月 3 日
    @buhi #7 我是想实现 3 点效果:单一 API ( set 方法)、set 过程有副作用(不是赋值这么简单)、派生类可以覆盖其中某个 set 方法。暂时没想到 TS 里有什么好的套路。
    SilentDepth
        9
    SilentDepth  
    OP
       2018 年 11 月 3 日
    我是想用 TS 实现这段代码的效果:

    https://jsfiddle.net/SilentDepth/3ydpra7q/
    kcats
        10
    kcats  
       2018 年 11 月 3 日
    @SilentDepth 这是标准的写法呀, 类型的 key 可以是不定的, 类也是一样, 比如

    type Map<T> = { [P: string]: T }

    和 @ts-ignore 完全不是一个东西, 代码里面理论上一定不要用 @ts-ignore 这个东西
    SilentDepth
        11
    SilentDepth  
    OP
       2018 年 11 月 3 日
    @kcats #10 我明白,我是说,这个 index signature 只是告诉编译器兼容未知的引用,并没有帮助类型推断,从结果上和 ts-ignore 没啥区别。
    kcats
        12
    kcats  
       2018 年 11 月 3 日
    @SilentDepth 这个性质是完全不一样的, ts-ignore 是跳过 ts 的静态类型检测, 意味着无论是对的还是错的都会被跳过, 这样带来的效果就是写这样的 ts 还不如直接写 js, 而上面说的形式是你明确知道这个类型的数据结构的.

    其实还有一种方法, 就是直接用 any 跳过:

    set(key, value) {
    (this as any)['key' + key](value)
    }
    FrankFang128
        13
    FrankFang128  
       2018 年 11 月 4 日
    那还不如用 JS 写
    SilentDepth
        14
    SilentDepth  
    OP
       2018 年 11 月 4 日
    @FrankFang128 #13 这意思是,这样的需求不适合用 TS 实现吗?(需求要点见 #8 )
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     792 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 23:00 PVG 07:00 LAX 15:00 JFK 18:00
    Do have faith in what you're doing.
    ubao msn 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