Typescript: Return type of function based on input value (enum)

你。 提交于 2020-01-24 07:56:46

问题


I'm storing some settings into local storage and I would like to type the responses when I get (and ideally also insert) values from/to the storage.

From what I've seen, the best way seems to be to use function overloading. So this is what I have now and it works:

export enum SettingsKey {
  hasOnboarded = 'hasOnboarded',
  phoneNumber = 'phoneNumber'
}

export async function getSetting(storage: Storage, key: SettingsKey.phoneNumber): Promise<string>
export async function getSetting(storage: Storage, key: SettingsKey.hasOnboarded): Promise<boolean>
export async function getSetting(storage: Storage, key: any) {
  return storage.get(key)
}

The thing that I don't like about this solution is that it's possible to forget adding a new element in the enum to the overload type definitions. Is there a way to enforce that all enum values are handled? Or is there maybe a better way to do this altogether?

I thought this would be a simple thing, a mapping from value hasOnboarded to return type boolean etc, but it's obviously not that easy.

It looks to me like conditional types might solve this problem, but I can't quite wrap my head around how it works.

I also saw this approach, but this seems like a little too much overhead.

Any insight would be greatly appreciated!


回答1:


You can use an extra type to map between the enum and the promise return type. We then add a generic parameter to getSettings that extends the SettingsKey enum and use the generic type to index into the mapping type. The generic parameter will be inferred based on the enum member we specify as an argument.

If the mapping type does not contain all keys of the enum we will get an error on the function.

export enum SettingsKey {
    hasOnboarded = 'hasOnboarded',
    phoneNumber = 'phoneNumber'
}

type SettingsKeyReturnType = {
    [SettingsKey.hasOnboarded]: boolean,
    [SettingsKey.phoneNumber]: string
}
export async function getSetting<K extends SettingsKey>(storage: Storage, key: K): Promise<SettingsKeyReturnType[K]> {
    return storage.get(key)
}
let a = getSetting(window.localStorage, SettingsKey.phoneNumber); // Promise<string>
let b = getSetting(window.localStorage, SettingsKey.hasOnboarded); // Promise<booelan> 

// We can also define a set function in a similar way
export async function setSetting<K extends SettingsKey>(storage: Storage, key: K, value: SettingsKeyReturnType[K]): Promise<void> {
   ///...
}


来源:https://stackoverflow.com/questions/52593184/typescript-return-type-of-function-based-on-input-value-enum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!