简体   繁体   English

TypeScript - 键入 object map 的函数与专有参数

[英]TypeScript - Typing an object map of functions with exclusive parameters

Here is an object where I keep functions by key:这是一个 object,我在其中按键保存功能:

export const questSetHelper: { [key in QuestSetHelper]: (player: Player, payload: FlagGender | FlagOrigin | FlagAdventure) => void } = {
  'setGender': setGender,
  'setOriginCircumstance': setOriginCircumstance,
  'setAdventureCircumstance': setAdventureCircumstance
}

I keep them as strings for easy handling from front-end to back-end passing strings that are used to determine which function to run.我将它们保留为字符串,以便从前端到后端传递字符串,用于确定要运行哪个 function。 Each function handles only one of the payload types.每个 function 只处理一种负载类型。

For example:例如:

export const setOriginCircumstance = (player: Player, payload: FlagOrigin): void => {
  if (player.quests['intro']?.flags)
    player.quests['intro'].flags['origin_circumstance'] = payload
  else
    throw new Error('Quest: intro - failed setOriginCircumstance')
}

When all these were typed to string , I had no type errors of course, but I want to have each of these function parameters explicitly typed.当所有这些都输入到string时,我当然没有类型错误,但我希望每个 function 参数都显式输入。

PROBLEM Obviously each function can ultimately handle ONE of the questSetHelper types of payload , but I want to assume that each function will be called correctly and passed the correct type (ie FlagGender payload will always go to setGender ). PROBLEM Obviously each function can ultimately handle ONE of the questSetHelper types of payload , but I want to assume that each function will be called correctly and passed the correct type (ie FlagGender payload will always go to setGender ).

Is there a better way to type this without changing the structure?有没有更好的方法在不改变结构的情况下输入这个?

I believe there are 2 options:我相信有两种选择:

Rely on type inference依赖类型推断

This is a minor change to your code这是对您的代码的一个小改动

export const setGender = (player: Player, payload: FlagGender): void => {}
export const setOriginCircumstance = (player: Player, payload: FlagOrigin): void => {}
export const setAdventureCircumstance = (player: Player, payload: FlagAdventure): void => {}

export const questSetHelper = {
  'setGender': setGender,
  'setOriginCircumstance': setOriginCircumstance,
  'setAdventureCircumstance': setAdventureCircumstance
}

Playground - inference 游乐场 - 推理

Use explicit typing to ensure all setters have correct types使用显式类型来确保所有设置器都具有正确的类型

In this approach, you start with defining QuestFlags .在这种方法中,您从定义QuestFlags开始。 After that, you use Key Remapping in Mapped Types to generate setters with appropriate names:之后,您使用Mapped Types 中的 Key Remapping来生成具有适当名称的 setter:

interface QuestFlags {
  gender: FlagGender
  originCircumstance: FlagOrigin
  adventureCircumstance: FlagAdventure
}

type QuestFlagsSetters = {
    [K in keyof QuestFlags & string as `set${Capitalize<K>}`]: (player: Player, payload: QuestFlags[K]) => void
};

export const questSetHelper: QuestFlagsSetters = {
  'setGender': setGender,
  'setOriginCircumstance': setOriginCircumstance,
  'setAdventureCircumstance': setAdventureCircumstance
}

Playground - Key remapping Playground - 按键重新映射

I see you use snake case for property names but camel case for setters.我看到您将蛇形大小写用于属性名称,而将驼峰大小写用于设置器。 This is easy to achieve as well:这也很容易实现:

interface QuestFlags {
  gender: FlagGender
  origin_circumstance: FlagOrigin
  adventure_circumstance: FlagAdventure
}

type SnakeCaseToPascalCase<S extends string> =
    S extends `${infer FirstWord}_${infer Rest}` ?
        `${Capitalize<Lowercase<FirstWord>>}${SnakeCaseToPascalCase<Rest>}` :
        Capitalize<Lowercase<S>>;


type QuestFlagsSetters = {
    [K in keyof QuestFlags & string as `set${SnakeCaseToPascalCase<K>}`]: (player: Player, payload: QuestFlags[K]) => void
};

export const questSetHelper: QuestFlagsSetters = {
  'setGender': setGender,
  'setOriginCircumstance': setOriginCircumstance,
  'setAdventureCircumstance': setAdventureCircumstance
}

Playground - Key remapping with snake_case changed to camelCase Playground - 使用 snake_case 重新映射的键更改为 camelCase

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM