typescript 在 Object.entries 的回调中丢失了类型怎么办?

2019-08-27 16:33:26 +08:00
 xiaoming1992
type Vegetable = "茄子" | "黄瓜" | "西红柿"

type List = {
  [key in Vegetable]: {
    price: number;
    num: number;
  };
}

const list: List = {
  "茄子": {
    price: 5,
    num: 2
  },
  "西红柿": {
    price: 5,
    num: 2
  },
  "黄瓜": {
    price: 5,
    num: 2
  },
}

Object.entries(list).map(([key, item]) => {
  // 这儿的 key 不再是 Vegetable, 而是 string, 怎么能维持它的 Vegetable 类型呢?
})
6188 次点击
所在节点    JavaScript
31 条回复
xiaoming1992
2019-08-28 06:57:47 +08:00
@zbinlin 对,被搞懵了
Oucreate
2019-08-28 13:47:12 +08:00
@azh7138m #4
> entries 定义是
> entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][]

虽然的确如此(可见于文件`lib.es2017.object.d.ts`),但我想不出需要 `<T>` 的情形,你能不能举个例子?谢谢啦!
azh7138m
2019-08-28 13:57:39 +08:00
@Oucreate 你就当它是 Map<string, T>吧
xiaoming1992
2019-08-28 15:03:08 +08:00
@wawaforya 才知道 Record 这么个东西,对我的类型定义是个很好的补充,感谢。虽然还是没什么卵用。。。


@zbinlin 写到 global 上不知道会不会对编译产生什么负担?

不知道怎么,按照 @azh7138m 写的,添加一个定义
``` typescript
interface ObjectConstructor {
entries<S extends string, T>(o: Record<S, T>): [S, T][];
}
```
没起作用。

或许 @optional 是对的,我不应该默认生成的 key 是 Vegetable,应该再次校验一下。
Oucreate
2019-08-28 15:08:52 +08:00
@azh7138m 呃,我还是不太明白……

为什么不都是第二种定义的 `any`,毕竟值不都是任意类型的么,所以会有什么特殊的情形需要 `<T>`?
Oucreate
2019-08-28 15:12:15 +08:00
修正:
“毕竟值不都是任意类型的么”

“毕竟值不都 *可以* 是任意类型的么”
azh7138m
2019-08-28 15:45:31 +08:00
@xiaoming1992
- 我没有写 extends


@Oucreate
特殊的情形 -> 把对象当 Map<string, T>用的时候
lhc70000
2019-08-28 16:17:15 +08:00
```
```ts
type Vegetable = "茄子" | "黄瓜" | "西红柿";
type Value = { price: number, num: number };

const list: Record<Vegetable, Value> = {
"茄子": {
price: 5,
num: 2
},
"西红柿": {
price: 5,
num: 2
},
"黄瓜": {
price: 5,
num: 2
},
};

(Object.entries(list) as [Vegetable, Value][]).map(([key, item]) => {
// ...
});
```

要是我的话就这么写。

或者就直接使用 Map,这样 list.entries() 能保持 key 的类型。
Oucreate
2019-08-28 18:04:23 +08:00
@azh7138m 这种情形下指定为 `<T>` 是为了统一和方便吗?
azh7138m
2019-08-28 18:55:55 +08:00
@Oucreate 一般是为了更好 /多的类型检查
xiaoming1992
2019-08-29 00:56:41 +08:00
@lhc70000 对,我后来就这么写的,省得到里面一个一个的给 key 加 as。

@Oucreate 对于复杂一些的对象,有类型检查和提示更方便啊,我现在恨不得所有变量都尽可能精确地描述它的类型。正常情况下 key 确实是 string,但是当我的 key 受到业余限定,只有这么确定的几种的话,用 a | b | c 来限定它们的类型会更方便。

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

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

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

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

© 2021 V2EX