你能在类型声明中得到准确的当前索引键吗?
Can you get the exact currently indexed key in types declaration?
我正在尝试创建一个相对简单的类型,该类型将强制对外部级别执行嵌套对象键引用。
为了更清楚地说明问题,这里有一个例子:
const obj = {
foo: {
name: 'bar',
ref: 'foo' // < this should reference the key of the parent
}
}
这在静态对象类型中显然不是问题,我们只需要检查 'foo'
,但我试图确保它是动态的,具有泛型类型参数。
我尝试了以下方法:
type InnerObject<K> = {
name: string,
ref: K,
}
type OuterObject<T, K extends keyof T> = {
[key in K]: InnerObject<K>
}
这几乎可以正常工作,对当前键的并集执行类型检查:
问题在于,它还允许将其他对象键传递给 ref
属性,而它显然不应该。
我一直在考虑以某种方式创建第三种泛型并将其传递给 Exclude
实用程序类型,即
type InnerObject<T, K extends keyof T, CurrentKey> = {
name: string,
ref: Exclude<CurrentKey, K>
}
但问题是,我想不出一种方法来传递索引对象的当前键,而无需在外部对象上编写显式缩减器/映射函数。
这是可行的,还是在 typescript 中根本不可能?
这是 link to the playground 的问题。
如果你有一个类似 Example
的类型想要转换成这个结构,你可以这样做:
type OuterObject<T extends object> = {
[K in keyof T]: InnerObject<K>
}
我们的想法是 mapping InnerObject<K>
超过 每个 K
keyof T
。
重要的是,这与您所写的不同之处在于,您是在整个联合 keyof T
上操作,而不是在联合中的每个元素上操作。这是 {[X in Y]: F<X>}
和 {[X in Y]: F<Y>}
之间的区别,前者对每个 属性 的计算结果可能不同。
这会产生您正在寻找的行为:
const obj: OuterObject<Example> = {
foo: {
name: 'whatever',
ref: 'foo',
},
bar: {
name: 'baz',
ref: 'foo' // error!
}
}
这对你有用吗?
我正在尝试创建一个相对简单的类型,该类型将强制对外部级别执行嵌套对象键引用。
为了更清楚地说明问题,这里有一个例子:
const obj = {
foo: {
name: 'bar',
ref: 'foo' // < this should reference the key of the parent
}
}
这在静态对象类型中显然不是问题,我们只需要检查 'foo'
,但我试图确保它是动态的,具有泛型类型参数。
我尝试了以下方法:
type InnerObject<K> = {
name: string,
ref: K,
}
type OuterObject<T, K extends keyof T> = {
[key in K]: InnerObject<K>
}
这几乎可以正常工作,对当前键的并集执行类型检查:
问题在于,它还允许将其他对象键传递给 ref
属性,而它显然不应该。
我一直在考虑以某种方式创建第三种泛型并将其传递给 Exclude
实用程序类型,即
type InnerObject<T, K extends keyof T, CurrentKey> = {
name: string,
ref: Exclude<CurrentKey, K>
}
但问题是,我想不出一种方法来传递索引对象的当前键,而无需在外部对象上编写显式缩减器/映射函数。
这是可行的,还是在 typescript 中根本不可能?
这是 link to the playground 的问题。
如果你有一个类似 Example
的类型想要转换成这个结构,你可以这样做:
type OuterObject<T extends object> = {
[K in keyof T]: InnerObject<K>
}
我们的想法是 mapping InnerObject<K>
超过 每个 K
keyof T
。
重要的是,这与您所写的不同之处在于,您是在整个联合 keyof T
上操作,而不是在联合中的每个元素上操作。这是 {[X in Y]: F<X>}
和 {[X in Y]: F<Y>}
之间的区别,前者对每个 属性 的计算结果可能不同。
这会产生您正在寻找的行为:
const obj: OuterObject<Example> = {
foo: {
name: 'whatever',
ref: 'foo',
},
bar: {
name: 'baz',
ref: 'foo' // error!
}
}
这对你有用吗?