首页 > 解决方案 > 如何将方法参数类型限制为父对象的键?

问题描述

您可以在以下代码片段中看到,我必须为 GIF 手动键入所有可能的字符串选项。但我想一定有更好的方法来实现这一点。任何人都可以帮助我吗?

type GIF =
  | 'dmg_high'
  | 'dmg_mid'
  | 'dmg_sustained'
  | 'quest_invite'
  | 'quest_start'
  | 'quest_finish'
  | 'error'

const tenor = {
  TENOR_URL: 'https://tenor.com/view/',
  GIFS: {
    dmg_high: ['damage-thats-alot-of-damage-jon-tron-gif-13054497'],
    dmg_mid: ['hanginthere-damage-gif-19763661'],
    dmg_sustained: [
      'ugh-guys-im-hit-jason-david-frank-red-zeo-ranger-tommy-oliver-power-rangers-zeo-gif-19564332',
    ],
    quest_invite: ['gandalf-looking-for-adventure-gif-13515313'],
    quest_start: [
      'adventure-lotr-hobbit-lord-of-gif-5730296',
      'lord-of-the-rings-ian-mc-kellen-gandalf-prepare-for-battle-prepare-gif-4879285',
    ],
    quest_finish: ['clapping-clap-applause-lotr-lord-gif-5730286'],
    error: 'debugging-we-bare-bears-panda-grizzly-polar-bear-gif-7268856',
  },
  gif(key: GIF) {

    if (!this.GIFS[key]) {
      return this.TENOR_URL + this.GIFS.error
    }

    return this.TENOR_URL + this.GIFS[key][0]
  },
}

export default tenor

标签: typescript

解决方案


对您的代码所做的最少更改可能是定义gifs为一个单独的常量,并使用keyof typeof gifs.

const gifs = {
    dmg_high: ['a'],
    dmg_mid: ['b'],
    dmg_sustained: ['c'],
    quest_invite: ['d'],
    quest_start: ['e','f'],
    quest_finish: ['g'],
    error: 'h',
}

type GIF = keyof typeof gifs

操场


然而...

在打字稿中,通常最好从类型接口开始,然后将常量创建为这些类型。所以你应该把这些键写两次。一旦进入界面(这是您的模板,确保您拥有正确格式的所有数据),然后进入数据(检查以确保其格式正确)。

这可以确保您的运行时数据与您的预期类型相匹配,这就是打字稿的重点。

这可能看起来像这样:

type GIF =
  | 'dmg_high'
  | 'dmg_mid'
  | 'dmg_sustained'
  | 'quest_invite'
  | 'quest_start'
  | 'quest_finish'

interface Tenor {
    TENOR_URL: string
    GIFS: { [key in GIF]: string[] } & { error: string }
    gif(key: GIF): string
}

这也修复了一个错误。很明显这error是特殊的,因为它是单个字符串,而不是像其他字符串那样的字符串数组。

把那个钥匙留在外面GIF不是一个有效的钥匙。这很重要,因为如果error传入,那么您的函数将执行this.GIFS['error'][0]返回错误 gif 字符串的第一个字母,而不是整个字符串,这不是您想要的。所以我们不允许error进入,GIF但我们确实在 gifs 对象的类型中将它作为正确的类型,因此它仍然可以被声明和访问。

现在您可以将对象创建为该类型,并从对运行时数据的类型检查中受益:

const tenor: Tenor = {
  TENOR_URL: 'https://tenor.com/view/',
  GIFS: {
    dmg_high: ['a'],
    dmg_mid: ['b'],
    dmg_sustained: ['c'],
    quest_invite: ['d'],
    quest_start: ['e','f'],
    quest_finish: ['g'],
    error: 'h',
  },
  gif(key: GIF) {
    if (!this.GIFS[key]) {
      return this.TENOR_URL + this.GIFS.error
    }

    return this.TENOR_URL + this.GIFS[key][0]
  },
}

操场


推荐阅读