如何使用打字稿中的字符串访问自定义界面的对象属性
How to access object properties of a custom interface using a string in typescript
我需要使用给定字符串作为键来动态访问我的对象的属性。
我已经检查了以下内容,但找不到我要找的答案:
TypeScript dynamic object properties
错误发生在这里:
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
}
此行为是有意的。
你在哪里访问你的状态
const entity: unknown = state.value[container][id]
state.value[container]
现在是 unknown
类型。您不能尝试访问它后面的 [id]
,因为 TS 不知道它是否存在于 state.value[container]
上。这是未知的。这就是使用 unknown 的缺点。如果您知道 API 响应,请为它们创建接口并将它们声明为您的状态的可能类型。
否则,如果你想强制它在没有类型的情况下工作,你必须使用 any
而不是 unknown.
您可以看到此行为已重现 here。您可以看到变量 b
的类型是未知的,并且已经抛出错误。如果您在界面中将类型更改为 any
,它会起作用,但您不会获得任何类型安全性。
我需要使用给定字符串作为键来动态访问我的对象的属性。
我已经检查了以下内容,但找不到我要找的答案:
TypeScript dynamic object properties
错误发生在这里:
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
}
此行为是有意的。
你在哪里访问你的状态
const entity: unknown = state.value[container][id]
state.value[container]
现在是 unknown
类型。您不能尝试访问它后面的 [id]
,因为 TS 不知道它是否存在于 state.value[container]
上。这是未知的。这就是使用 unknown 的缺点。如果您知道 API 响应,请为它们创建接口并将它们声明为您的状态的可能类型。
否则,如果你想强制它在没有类型的情况下工作,你必须使用 any
而不是 unknown.
您可以看到此行为已重现 here。您可以看到变量 b
的类型是未知的,并且已经抛出错误。如果您在界面中将类型更改为 any
,它会起作用,但您不会获得任何类型安全性。