键入泛型typescript结构时出现问题
我想处理以下数据:键入泛型typescript结构时出现问题,typescript,Typescript,我想处理以下数据: const stateTest = { natures : { nature1: { amounts: { column1: 10, column2: 10, }, natureDetails : { detail1 : { amounts: { column1: 10, column2: 10,
const stateTest = {
natures : {
nature1: {
amounts: {
column1: 10,
column2: 10,
},
natureDetails : {
detail1 : {
amounts: {
column1: 10,
column2: 10,
},
descriptionShown: false
}
}
}
}
}
其中列列表(此处为column1,column2)是一个参数
因此,我声明了以下类型和接口
type State<T extends GenericColumnList> = T & {
natures: naturesSet<T>
}
type GenericColumnList = Record<string, number>
type naturesSet<T extends GenericColumnList> = Partial<Record<string, RowNature<T>>>
export interface RowNature<T extends GenericColumnList> {
natureDetails: NatureDetailsSet<T>
amounts: T
}
type NatureDetailsSet<T> = Partial<Record<string, RowDetailNature<T>>>
export interface RowDetailNature<T> {
amounts: T
descriptionShown: boolean
}
即:
const stateTest: State<MyColumns> = {
natures : {
nature1: {
amounts: {
column1: 10,
column2: 10,
},
natureDetails : {
detail1 : {
montants: {
column1: 10,
column2: 10,
},
descriptionShown: false
}
}
}
}
}
const stateTest:状态={
性质:{
性质1:{
金额:{
专栏1:10,
专栏2:10,
},
性质详情:{
详情1:{
蒙塔人:{
专栏1:10,
专栏2:10,
},
描述显示:false
}
}
}
}
}
typescript编译器抱怨说
“MyColumns类型不符合记录”,我不明白为什么。类型记录
有一个字符串。接口
MyColumns
没有索引签名,因此类型不兼容
有这样一个概念,即没有显式索引签名的类型被视为与可索引类型兼容,只要所有已知属性都符合索引签名。。。但这不适用于声明为
接口的类型
;它仅适用于匿名类型(或此类匿名类型的别名)。GitHub中有一个公开的问题,正在讨论这个问题。事实证明,就目前而言,这种行为是不正确的
因此,处理此问题的一种方法是将MyColumns
设置为匿名类型的类型别名,而不是任何接口,如下所示:
export type MyColumns = {
column1?: number
column2?: number
}
然后,您需要在GenericColumnList
的域中包含undefined
,因为MyColumns['column1']
的类型是number | undefined
,而不仅仅是number
(假设我们使用的是推荐的--严格的编译器选项包括):
在这里,我们将属性设置为可选(?
),原因与前面添加的| undefined
相同:使可选/缺少的键在存在--stricnullchecks
的情况下兼容
这需要在代码周围撒一些
:
type State<T extends GenericColumnList<T>> = T & {
natures: NaturesSet<T>
}
type NaturesSet<T extends GenericColumnList<T>> = Partial<Record<string, RowNature<T>>>
export interface RowNature<T extends GenericColumnList<T>> {
natureDetails: NatureDetailsSet<T>
amounts: T
}
type State=T&{
自然:自然集
}
类型属性set=Partial
导出接口RowNature{
natureDetails:NatureDetailsSet
金额:T
}
同样,您的任务将有效:
const stateTest: State<MyColumns> = {
natures: {
nature1: {
amounts: {
column1: 10,
column2: 10,
},
natureDetails: {
detail1: {
amounts: {
column1: 10,
column2: 10,
},
descriptionShown: false
}
}
}
}
}; // okay
const stateTest:状态={
性质:{
性质1:{
金额:{
专栏1:10,
专栏2:10,
},
性质详情:{
详情1:{
金额:{
专栏1:10,
专栏2:10,
},
描述显示:false
}
}
}
}
}; // 可以
大概是montants
是个打字错误吗?好家伙++++
const stateTest: State<MyColumns> = {
natures: {
nature1: {
amounts: {
column1: 10,
column2: 10,
},
natureDetails: {
detail1: {
amounts: {
column1: 10,
column2: 10,
},
descriptionShown: false
}
}
}
}
}; // okay
type GenericColumnList<T> = { [K in keyof T]?: number }
type State<T extends GenericColumnList<T>> = T & {
natures: NaturesSet<T>
}
type NaturesSet<T extends GenericColumnList<T>> = Partial<Record<string, RowNature<T>>>
export interface RowNature<T extends GenericColumnList<T>> {
natureDetails: NatureDetailsSet<T>
amounts: T
}
const stateTest: State<MyColumns> = {
natures: {
nature1: {
amounts: {
column1: 10,
column2: 10,
},
natureDetails: {
detail1: {
amounts: {
column1: 10,
column2: 10,
},
descriptionShown: false
}
}
}
}
}; // okay