很难用清晰的语言解释这一点。
在下面的Setter界面中,我将'field'键的类型限制为keyof Store(在这种情况下'name'|'age')。
然后对于'value'键,我想获得给定'field'键的值的类型。
这就是我现在所拥有的:
interface Store {
name: string,
age: number
}
interface Setter<T = Store, K extends keyof T> {
type: 'SET_VALUE',
field: K
// for key: 'name', want type value: string
// for key: 'age', want type value: number
value: T[K]
}
// Should error
const invalidName: Setter = {
type: 'SET_VALUE',
field: 'name',
value: 30,
}
// Should work
const validName: Setter = {
type: 'SET_VALUE',
field: 'name',
value: 'hello',
}
// Should work
const validAge: Setter = {
type: 'SET_VALUE',
field: 'age',
value: 30,
}
答案 0 :(得分:2)
通用T
没有为您做任何事情,因为您始终希望它为Store
。因此,您应该首先删除T
泛型,并将T
的实例替换为Store
:
interface Store {
name: string,
age: number
}
interface Setter<K extends keyof Store> {
type: 'SET_VALUE',
field: K
value: Store[K]
}
接下来,您希望Setter
成为existential type,这意味着您只需要声明某个没有类型参数的Setter
,而TypeScript会将其解释为某些值K
满足type参数,而不必指定它。好吧,TypeScript没有存在类型(没有疯狂的解决方法)所以你不能这样做。
你可以做的是做一个帮助函数,它为你提供一个对象字面值,并且推断类型为K
,所以你没有把它写出来:
function asSetter<K extends keyof Store>(setter: Setter<K>): Setter<K> {
return setter;
}
让我们看看它的实际效果:
// error as desired
const invalidName = asSetter({
type: 'SET_VALUE',
field: 'name',
value: 30,
});
// works, inferred as Setter<'name'>
const validName = asSetter({
type: 'SET_VALUE',
field: 'name',
value: 'hello',
});
// works, inferred as Setter<'age'>
const validAge = asSetter({
type: 'SET_VALUE',
field: 'age',
value: 30,
});
希望有所帮助!
答案 1 :(得分:1)
以下作品:
class Setter<K extends keyof T, T = Store> {
constructor(public field: K, public value: T[K]) { }
type: 'SET_VALUE'
}
const anotherValidName = new Setter('name', 'thename')
const anotherValidAge = new Setter('age', 30)
您也可以在不使用类复制密钥的情况下执行此操作:
var span = $('span');
span.remove();
$('li').prepend(span);