【问题标题】:How to access object properties of a custom interface using a string in typescript如何使用打字稿中的字符串访问自定义界面的对象属性
【发布时间】:2021-02-24 06:38:17
【问题描述】:

我需要使用给定的字符串作为键来动态访问我的对象的属性。

我已检查以下内容,但找不到我正在寻找的答案:

TypeScript dynamic object properties

Typescript dynamic access property

错误发生在这里:

state.value[container][id] // TS2571: Object is of type 'unknown'

当调用方法“getEntity”时,我应该为属性传递一个 ENUM 而不是字符串吗?

下面是我的代码的简化示例 - 错误在第 57 行和第 69 行:

// interfaces for entity types - including these in this example seems unnecessary
import {
  TaskFinances,
  Plan,
  Boundary,
  BoundaryMapList
} from 'DTOs'

// for pulling data from REST
import axios, { AxiosResponse } from 'axios'

// VueJS composition AIP components
import { ref } from '@vue/composition-api'

// I want to imply that the State interface below is made up of string:unknown pairs
// so that I can reference it using a string key in the <getEntity> method below

interface Stately {
  [key: string]: unknown
}
interface State extends Stately {
  plans: { [key: number]: Plan };
  taskFinances: { [key: number]: TaskFinances };
  boundaryPointsByField: Boundary[];
}

const props: State = {
  plans: {},
  taskFinances: {},
  boundaryPointsByField: []
}

const state = ref(props)
// I reference the properties of state using state.value.xxx because it is using the Vue3 Composition API Ref syntax

// Reduced to 2 lines following D.R.Y. principles
function getTaskFinances(activityId: number): Promise<TaskFinances> {
  const taskFinances = getEntity(activityId, 'taskFinance', 'taskFinances') as unknown as Promise<TaskFinances>
  return taskFinances
}

// Reduced to 2 lines following D.R.Y. principles
function getBoundaryPointsByField(fieldId: number): Promise<BoundaryMapList> {
  const boundaryPoints = getEntity(fieldId, 'boundaryPointsByField', 'boundaryPointsByField') as unknown as Promise<BoundaryMapList>
  return boundaryPoints
}

// Reduced to 2 lines following D.R.Y. principles
function getPlan(planId: number): Promise<Plan> {
  const plan = getEntity(planId, 'plan', 'plans') as unknown as Promise<Plan>
  return plan
}

// generic method to return requested entities and add them to my state object
async function getEntity(id: number, api: string, container: string): Promise<unknown> {
  try {
    const entity: unknown = state.value[container][id] // THROWS typescript error -TS2571: Object is of type 'unknown'-
    if (entity) {
      return entity
    }
  } catch (err) {
    console.log(container, id, err)
  }

  const url = `${api}${id}`
  try {
    const { data }: AxiosResponse<unknown> = await axios.get(url)
    console.log(api + ':', data)
    state.value[container][id] = data  // THROWS typescript error -TS2571: Object is of type 'unknown'-
    return data
  } catch (err) {
    console.error(err)
  }
}

// interface for my exported uiState object - I use this interface elsewhere in the app so I am exporting it
export interface IUIState {
  getBoundaryPointsByField: (fieldId: number) => Promise<BoundaryMapList>;
  getTaskFinances: (activityId: number) => Promise<TaskFinances>;
  getPlan: (planId: number) => Promise<Plan>;
}

// export my uiState object
export const uiState: IUIState = {
  getBoundaryPointsByField,
  getTaskFinances,
  getPlan
}

【问题讨论】:

  • 你能用更好的类型吗?例如。 container: string 应该是 keyof 什么的。
  • keyof 对我来说是新的,因为我对 TypeScript 很陌生(我想这表明了!) - 我现在正在研究如何在这种情况下实现它,但如果你有任何建议我会感谢他们;)感谢您的时间@johnsharpe
  • 没有得到它 ;( ``` async function getEntity(id: number, api: string, container: K): Promise { ```
  • 感谢@rie,但这让我的 props 对象完全通用。将容器作为与通用字符串相对的 keyof State 传递对我来说更有意义(正如 johnsharpe 建议的那样),但我不知道如何正确地做到这一点。
  • @user2115620 查看这个函数getEntity 的参数并给出这个state.value[container][id],你确定你会有dynamic“实体工厂”用数字命名吗?因为这实际上会评估为:state.value.getAnotherMethod['123'].

标签: typescript vue.js vue-composition-api


【解决方案1】:

这种行为是有意的。

您在此处访问您所在州的位置

 const entity: unknown = state.value[container][id]

state.value[container] 现在是unknown 类型。你不能尝试访问它后面的[id],因为 TS 不知道它是否存在于 state.value[container] 上。这是未知的。这就是使用未知数的缺点。如果您知道您的 API 响应,请为它们创建接口并将它们声明为您的状态的可能类型。 否则,如果你想强制它在没有类型的情况下工作,你必须使用 any 而不是 unknown。

您可以看到此行为重现 here。您可以看到变量 b 的类型为 unknown 并且已经抛出错误。如果您在界面中将类型更改为any,它会起作用,但您不会获得任何类型安全性。

【讨论】:

    猜你喜欢
    • 2016-09-22
    • 2023-01-16
    • 2021-12-16
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    相关资源
    最近更新 更多