Since the introduction of mapped tuple types in typescript 3.1, I was eager to see if this code sample would function as expected:
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'
})
Unfortunately, it did not work as expected. The errors encountered were as follows:
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'
~
The second error seems to be a result of the first error and is not a major concern. However, the first error is the critical one.
The keys are an array of keyof SettingKey
, and I expected SettingKey[K]
to be an array of types of the specified properties (i.e., in the sample code provided, it should be ['en' | 'sl', number]
). According to the pull request introducing the typescript feature:
If T is an array type S[] we map to an array type R[], where R is an instantiation of X with S substituted for T[P].
However, this might only apply to mapped types, and since I am using a lookup type here, it seems like that might be the reason it's not working as expected.
Even though I believe my intention is clear, I am wondering if this can be achieved in a type-safe manner in typescript.