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

2018-11-03 15:58:17 +08:00
 SilentDepth

比如有这么一个类:

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 节点。

5681 次点击
所在节点    JavaScript
15 条回复
kernel
2018-11-03 16:04:40 +08:00
不可能的,你把 set$name 方法前的 set$去掉还有一点可能
des
2018-11-03 16:44:35 +08:00
不可能
vghdjgh
2018-11-03 16:52:35 +08:00
SilentDepth
2018-11-03 17:24:12 +08:00
@vghdjgh #3 Options 里开启 noImplicitAny 后,错误提示出现。
kcats
2018-11-03 18:05:53 +08:00
SilentDepth
2018-11-03 21:00:17 +08:00
@kcats #5 这是不是和 @ts-ignore 一个效果……

再尝试搜索了一下,放弃从 TS 寻找原生解决方案了。个人觉得这也算 JS 编码的常见套路,希望 TS 早日能支持这个特性吧。
buhi
2018-11-03 21:11:01 +08:00
这个虽然是 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
2018-11-03 21:22:09 +08:00
@buhi #7 我是想实现 3 点效果:单一 API ( set 方法)、set 过程有副作用(不是赋值这么简单)、派生类可以覆盖其中某个 set 方法。暂时没想到 TS 里有什么好的套路。
SilentDepth
2018-11-03 21:37:10 +08:00
我是想用 TS 实现这段代码的效果:

https://jsfiddle.net/SilentDepth/3ydpra7q/
kcats
2018-11-03 21:52:20 +08:00
@SilentDepth 这是标准的写法呀, 类型的 key 可以是不定的, 类也是一样, 比如

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

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

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

set(key, value) {
(this as any)['key' + key](value)
}
FrankFang128
2018-11-04 01:00:49 +08:00
那还不如用 JS 写
SilentDepth
2018-11-04 22:54:22 +08:00
@FrankFang128 #13 这意思是,这样的需求不适合用 TS 实现吗?(需求要点见 #8 )
azh7138m
2018-11-04 23:58:55 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/504101

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX