reactjs - 对象中的打字稿类型值
问题描述
试图强类型数据格式化函数。功能很简单,
输入:
const eleOfArray = {
a: 1,
b: "string",
c: [1, 2, 3]
}
输出:
const eleOfArray = {
a: {
value: 1,
component: 1
},
b: {
value: "string",
component: "string"
},
c: {
value: [1, 2, 3],
component: [1, 2, 3]
}
}
功能:
export function tableDataFormatter<T>(d: T) {
const formatedData: ITableData<T> = {}
Object.keys(d).forEach((key: string) => {
// tslint:disable-next-line:ban-ts-ignore
// @ts-ignore
formatedData[key] = {
// tslint:disable-next-line:ban-ts-ignore
// @ts-ignore
value: d[key as keyof T],
component: d[key as keyof T]
}
})
return formatedData
}
界面:
interface ITableData<T> {
readonly [key: keyof T]: {
readonly component: React.ReactNode
readonly value: T[keyof T]
}
}
我在使用此代码时遇到的问题是,当我使用tableDataFormatter
它时,它value
总是显示string | number
.
用法:
public formatData<IBenefit> (data: ReadonlyArray<IBenefit>): ReadonlyArray<ITableData<IBenefit>> {
return super.formatData(data).map((d: ITableData<IBenefit>) => ({
...d,
stores: {
...d.stores,
component: <Addon addonValues={d.stores.value} />
// d.stores.value should be an Array but it's being shown as ReactText/string
}
}))
}
所以我必须抑制错误,因为该功能按预期工作,我明确指定value
为readonly value: T[keyof T]
解决方案
您的ITableData<T>
界面不是有效的 TypeScript。具体来说,您正在尝试使用限制为的索引签名keyof T
,但唯一允许的索引签名类型是string
和number
。相反,您应该考虑使用映射类型而不是接口。它会给你你想要的映射:
type ITableData<T> = {
readonly [K in keyof T]: {
readonly component: React.ReactNode
readonly value: T[K]
}
}
请注意嵌套value
属性是 typeT[K]
而不是T[keyof T]
。T[keyof T]
将是所有值类型的联合,T
并且从每个键到每个值的映射都会丢失。但这T[K]
意味着对于每个键K
,嵌套属性与索引value
的原始属性的类型相同。这是避免问题的方法。 T
K
string | number
然后,tableDataFormatter()
我将更改一些注释和断言,如下所示:
// strip off the readonly modifier for the top level properties
type Mutable<T> = { -readonly [K in keyof T]: T[K] };
// explicitly declare that the function returns ITableData<T>
export function tableDataFormatter<T extends Record<keyof T, React.ReactNode>>(
d: T
): ITableData<T> {
// assert that the return value will be ITableData<T> but make it
// mutable so we can assign to it in the function without error
const formatedData = {} as Mutable<ITableData<T>>;
// assert that Object.keys(d) returns an array of keyof T types
// this is not generally safe but is the same as your "as keyof T"
// assertions and only needs to be done once.
(Object.keys(d) as Array<keyof T>).forEach(key => {
formatedData[key] = {
value: d[key],
component: d[key]
}
})
return formatedData
}
希望这能按您现在期望的方式工作。祝你好运!
推荐阅读
- c# - 无法在动态数据表中读取 Kendo Pivot Grid MVC 中未定义的属性“值”
- amazon-s3 - 使用 S3 签名 URL 到 PUT 对象时出现间歇性 403 CORS 错误
- redhat - 如何在 Red Hat Developer Studio 12.9.0.GA 中安装 Subversion?
- java - 使用缺少 .prj 文件的 GeoTools 从 UTM 转换为 WGS84?
- azure - 如何对 https://management.azure.com api 进行身份验证?
- python - 无法从 tensorflow.keras.metrics 导入指标
- php - 切换url时加载不同的视图文件
- java - 尝试从 oracle 11.2.0.3 升级到 oracle-12.1.0.2-32 时出错
- azure - 是否有将 CRM 链接到 Azure DevOps 的 API
- reporting-services - SSRS 2016 修复矩形的大小