【问题标题】:typescript mapped tuple lookup types?打字稿映射的元组查找类型?
【发布时间】:2018-11-11 03:49:35
【问题描述】:

既然 typescript 3.1 引入了 mapped tuple types,我希望这个代码示例能够工作:

export interface SettingKey {
    General_Language: 'en' | 'sl';
    Map_InitialLongitude: number;
    Map_InitialLatitude: number;
}

export function fetchSetting<K extends (keyof SettingKey)[]>
        (...keys: K): Promise<SettingKey[K]> {
    return null as any;
}
fetchSetting('General_Language', 'Map_InitialLongitude').then(x => {
    return x['General_Language'] === 'de' // would want compilation error 'de' not in 'en' | 'sl'
})

但事实并非如此。错误是:

ttt.ts:7:83 - error TS2536: Type 'K' cannot be used to index type 'SettingKey'.

7 export function fetchSetting<K extends (keyof SettingKey)[]>(...keys: K): Promise<SettingKey[K]> {
                                                                                    ~~~~~~~~~~~~~

ttt.ts:11:12 - error TS2571: Object is of type 'unknown'.

11     return x['General_Language'] === 'de'
          ~

显然,第二个错误是第一个错误的结果,所以这不是真正的问题。第一个是有问题的。

keys 是一个keyof SettingKey 的数组,所以我希望SettingKey[K] 是一个列出的属性类型的数组(所以,具体来说,在我放置的代码示例中,它将是['en' | 'sl', number]。来自pull request introducing the typescript feature

如果 T 是一个数组类型 S[],我们将映射到一个数组类型 R[],其中 R 是 X 的一个实例,其中 S 代替了 T[P]。

但我猜这仅适用于映射类型,这里我有一个查找类型,这就是我猜它不起作用的原因?

我想我想表达的很清楚;这可以在打字稿中进行类型安全吗?

【问题讨论】:

  • 如果你想要['en' | 'sl', number],那么你应该查找x[0],而不是x['General_Language']。这是与映射元组的错误不同的错误。

标签: typescript


【解决方案1】:

要拥有一个映射元组,您需要一个映射类型,它将原始元组(在类型参数 K 中)映射到新的元组类型

export interface SettingKey {
    General_Language: 'en' | 'sl';
    Map_InitialLongitude: number;
    Map_InitialLatitude: number;
}

type SettingKeyProp<P extends keyof SettingKey> = SettingKey[P]
type SettingKeyArray<K extends { [n: number]: keyof SettingKey }> = {
  [P in keyof K]: K[P] extends keyof SettingKey ? SettingKey[K[P]]: never 
} 
export function fetchSetting<K extends (keyof SettingKey)[]>
        (...keys: K): Promise<SettingKeyArray<K>> {
    return null as any;
}
fetchSetting('General_Language', 'Map_InitialLongitude').then(x => {
    // x[0] is 'en' | 'sl'
    return x[0] === 'de' /// since you want a tuple, you should index by number not name
})

如果你想按名称索引也是可能的,但映射类型应该映射数组中的值而不是数组中的键:

type SettingKeyArray<K extends { [n: number]: keyof SettingKey }> = {
  [P in K[number]]: SettingKey[P] 
} 
export function fetchSetting<K extends (keyof SettingKey)[]>
        (...keys: K): Promise<SettingKeyArray<K>> {
    return null as any;
}
fetchSetting('General_Language', 'Map_InitialLongitude').then(x => {
    // you can access by name
    return x.General_Language === 'de' 
}) 

【讨论】:

  • 太好了,谢谢!注意SettingKeyArray 的类型参数看起来有点吓人,我发现说type SettingKeyArray&lt;K extends (keyof SettingKey)[]&gt; = ... 也可以。
猜你喜欢
  • 2019-11-19
  • 2023-03-15
  • 2022-12-07
  • 2022-08-17
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
相关资源
最近更新 更多