【问题标题】:How to define an unknown object property key in typescript如何在打字稿中定义未知对象属性键
【发布时间】:2020-11-24 02:49:28
【问题描述】:

使用 Vue 组合 API,我们创建了以下可组合:

import { computed, reactive, SetupContext, ref } from '@vue/composition-api'

export const useApplications = (root: SetupContext['root']) => {
  const applications = reactive({
    1: {
      name: ref(root.$t('app1.name')),
      description: ref(root.$t('app1.description')),
      formName: 'app1form',
    },
    2: {
      name: ref(root.$t('app2.name')),
      description: ref(root.$t('app2.description')),
      formName: 'app2form',
    },
  })

  const getApplication = (id: string) => {
    return applications[id]
  }

  return {
    applications: computed(() => applications),
    getApplication,
  }
}

虽然代码运行良好,但它会产生 TS 错误:

@typescript-eslint/no-unsafe-return:任何类型值的不安全返回

当悬停在applications 部分时,很明显 typescript 可以识别除属性名称 (1) 之外的类型:

我们是否需要创建一个interface 来解决这个问题,我们是否必须重新定义界面中的每个属性?我试过这样的东西,但它是不正确的:

interface IApplication {
  [key]: string {
    name : string
    description: string
    formName: string
  }
}

【问题讨论】:

  • 出于好奇,为什么要使用带有数字键的对象而不是数组?
  • 对于 limitations 在 Vue 2 的组合 API 中带有数组
  • 如果您知道所涉及的库,我将不得不相信这是一个答案。否则,它似乎无法解释任何事情。
  • 我第一次使用array。但是 Vue 2 中的 Vue 反应性系统有 issues 使用这种方法。无论如何感谢您的帮助,非常感谢。

标签: javascript typescript vue.js


【解决方案1】:

TypeScript 通常不键入内容,因此它们可以被任何字符串键索引。正如你所说,你可以为它定义一个接口:

interface IApplications {
    [key: string]: {
        name : string;
        description: string;
        formName: string;
    };
}
// ...
const applications: IApplications = ...

或者你可以只使用一个类型作为对象部分,然后使用内置的Record 类型作为applications

interface IApplication {
    name : string;
    description: string;
    formName: string;
}
// ...
const applications: Record<string, IApplication> = ...

或者将两者结合起来:

interface IApplication {
    name : string;
    description: string;
    formName: string;
}
type IApplications = Record<string, IApplication>;

(或者您可以内联IApplication 部分。或者... :-))

【讨论】:

  • 谢谢,这正是我想要的。我只是希望不必重新定义属性namedescriptionformName,因为 TS 通过自动解释已经知道它们。但似乎我们需要创建一个完整的对象。
  • @DarkLite1 - 是的,如果它能推断出那部分就好了。也许这是可能的(太多了),我只是没有立即看到它。 :-)
【解决方案2】:

根据reactive函数的参数结构,接口可以定义为:

interface IApplication {
  [key:string]:{
        name : string
       description: string
       formName: string
  }
}

const applications = reactive<IApplication>({ ...
                                      

但我想建议另一种方法,将 applications 定义为 reactive 参数,其中有一个数组作为值:


import { computed, reactive, SetupContext, ref ,toRef} from '@vue/composition-api'
interface IApplication {
    name : string
    description: string
    formName: string
  }

export const useApplications = (root: SetupContext['root']) => {
  const state= reactive<Array<IApplication>>({ applications :
    [{
      name: ref(root.$t('app1.name')),
      description: ref(root.$t('app1.description')),
      formName: 'app1form',
    },
     {
      name: ref(root.$t('app2.name')),
      description: ref(root.$t('app2.description')),
      formName: 'app2form',
    }],
  })

  const getApplication = (index: number) => {
    return state.applications[index]
  }

  return {
    applications: toRef(state,'applications'),
    getApplication,
  }
}

【讨论】:

    猜你喜欢
    • 2014-07-17
    • 2021-12-09
    • 2021-09-29
    • 2021-12-16
    • 2021-03-04
    • 2018-01-16
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多