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 类型呢?
})
     1 
                    
                    geekdada      2019-08-27 16:46:51 +08:00 
                    
                    运行在 Runtime 里的还是 JS 代码,所以你在运行时拿到的类型是 string。 
                 | 
            
     2 
                    
                    ochatokori      2019-08-27 16:49:26 +08:00 via Android 
                    
                    可能我不会 ts,用 ts 有很多这样类似的问题 
                实在不行就<Vegetable>  | 
            
     3 
                    
                    Hypn0s      2019-08-27 16:51:53 +08:00 
                    
                    ```javascript 
                Object.entries(list).map(([trueKey, item]) => { let key1 = <Vegetable>trueKey; let key2 = trueKey as Vegetable; }) ``` 实在没办法  | 
            
     4 
                    
                    azh7138m      2019-08-27 16:52:16 +08:00    entries 定义是 
                entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][]; entries(o: {}): [string, any][]; 你得自己提供一个 entries 来 hack 这个 key 的类型  | 
            
     5 
                    
                    azh7138m      2019-08-27 17:04:45 +08:00 
                    
                    目前在 ts 里面构造出一个数组长度是一个对象 key 的数量,这种操作很难做通用实现 
                value 类型固定的,给个 xjb 的做法的话 在代码前面写一个 interface ObjectConstructor { entries<O>(o: O): [keyof O, O[keyof O]][]; } 后面的 entries 就能拿到类型了 但是我不推荐这样子写,因为不通用 如果场景足够单一,可以补充一个 entries 的定义,如果还有别的场景,建议手动指定 key 的类型  | 
            
     6 
                    
                    wawaforya      2019-08-27 17:05:29 +08:00 
                    
                    ``` 
                Object.entries(list).map(([key, item]: [Vegetable, { price: number; num: number }]) => { // 可以给参数加个类型定义 }); ```  | 
            
     7 
                    
                    xiaoming1992   OP @wawaforya 没用,提示不能将 string 赋给 Vegetable 
                 | 
            
     8 
                    
                    jatai      2019-08-27 17:33:05 +08:00 via Android 
                    
                    什么? ts 也设置类型? 前端高手不都是用 any 吗 
                 | 
            
     9 
                    
                    xiaoming1992   OP  | 
            
     10 
                    
                    xiaoming1992   OP 可能因为我菜吧 /(ㄒoㄒ)/~~ 
                 | 
            
     11 
                    
                    azh7138m      2019-08-27 17:43:14 +08:00 
                    
                    @xiaoming1992 并不,他们不是一个概念,补充一个新的签名是重载,js 里面没有这个概念 
                 | 
            
     12 
                    
                    xiaoming1992   OP @azh7138m 不是说`重载`必须要将`函数定义`紧挨着`interface`写吗?还可以半中间插进来?王自如觉得很 awesome👍 
                 | 
            
     13 
                    
                    azh7138m      2019-08-27 18:03:22 +08:00 
                    
                    
                 | 
            
     14 
                    
                    optional      2019-08-27 18:19:26 +08:00 
                    
                    type List = { 
                [key in Vegetable]: { price: number; num: number; }; } 这只能保证 list[Vegetable] 的 type 是 {price,num},并不能保证所有 key 都是{price,num} 不信你试试 const list = {} as List const o = list['any'] list['xx'] = 1; 是合法的,list['any'] 的类型是 any 能保证的是 type List = { [key : Vegetable]: { price: number; num: number; }; } 但是这又是不合法的。  | 
            
     15 
                    
                    wawaforya      2019-08-27 18:27:08 +08:00    @xiaoming1992 , 我这边可以的啊,难道是版本问题?我 typescript 的版本是 3.5.3 
                PS: List 其实可以用 Record 来定义,Record<Vegetable, { price: number; num: number }>  | 
            
     16 
                    
                    xiaoming1992   OP  | 
            
     17 
                    
                    optional      2019-08-27 18:45:41 +08:00 
                    
                    @xiaoming1992 不会报错 
                 | 
            
     18 
                    
                    zbinlin      2019-08-27 22:00:17 +08:00 
                    
                    entries 的签名写死了 string,你试试加上这个自动推导的签名: 
                declare global { interface ObjectConstructor { entries<S extends string, T>(list: { [key in S]: T }): [S, T][]; } }  | 
            
     19 
                    
                    xiaoming1992   OP @zbinlin .如果这么搞的话,那什么 map foreach 什么的都要声明。。。 
                 | 
            
     20 
                    
                    zbinlin      2019-08-28 00:12:07 +08:00 
                    
                    @xiaoming1992 不需要呀,为什么需要,map, foreach 这些已经能正确地推导出数组里的类型的。 
                 | 
            
     21 
                    
                    xiaoming1992   OP @zbinlin 对,被搞懵了 
                 | 
            
     22 
                    
                    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>` 的情形,你能不能举个例子?谢谢啦!  | 
            
     24 
                    
                    xiaoming1992   OP  | 
            
     25 
                    
                    Oucreate      2019-08-28 15:08:52 +08:00     | 
            
     26 
                    
                    Oucreate      2019-08-28 15:12:15 +08:00 
                    
                    修正: 
                “毕竟值不都是任意类型的么” → “毕竟值不都 *可以* 是任意类型的么”  | 
            
     27 
                    
                    azh7138m      2019-08-28 15:45:31 +08:00 
                    
                    
                 | 
            
     28 
                    
                    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 的类型。  | 
            
     31 
                    
                    xiaoming1992   OP  |