Typescript 通用键约束:必须是特定对象类型的键
我不确定这是否可能,但我已经很接近了 如果我有此对象/形状:Typescript 通用键约束:必须是特定对象类型的键,typescript,Typescript,我不确定这是否可能,但我已经很接近了 如果我有此对象/形状: export const initialState: State = { foods: { filter: '', someForm: { name: '', age: 2, }, someFormWithoutAnAge: { name: '', }, } }; d
export const initialState: State = {
foods: {
filter: '',
someForm: {
name: '',
age: 2,
},
someFormWithoutAnAge: {
name: '',
},
}
};
declare function pickAForm<R extends keyof State, S extends keyof State[R]>(key1: R, key2: S): void;
但我一点也不知道该怎么做。总结如下:
pickAFormWithAge('foods', 'someForm') // Passes
pickAFormWithAge('foods', 'someFormWithoutAge') // Should fail, does not look like {age: number}
pickAFormWithAge('foods', 'blah') // Should fail, not a key
我能做到这一点的唯一方法是: a。约束数据结构以匹配字符串文字,而不是相反。
B将数据结构作为函数参数传递
const state = {
foods: {
filter: '',
someForm: {
name: 'Some form',
age: 2
},
someFormWithoutAnAge: {
name: 'other form',
priority: 10
}
}
};
interface HasAge { age: number }
// IMPLEMENTATION
function getForm<O extends {[P in P1]: {[P in P2]: HasAge}}, P1 extends string, P2 extends string>(o: O, p1: P1, p2: P2) {
return (o[p1] as any)[p2] as any;
}
// USAGE
const form1 = getForm(state, 'foods', 'someForm'); // GOOD
const form2 = getForm(state, 'foods', 'someFormWithoutAnAge'); // ERROR
const form3 = getForm(state, 'foods', 'blah'); // ERROR
如果您将
State
的定义添加到您的问题中,这会有所帮助。State看起来就像initialState一样。所以想一想,你说有效的部分在操场上不起作用,它会产生这样的错误:类型为“someForm”的参数不能赋值给类型为“never”的参数
Odd,它在VS代码中工作得很好,在webpack中编译得很好。也许操场使用的是旧版本?但是它在正则类型脚本中工作。尝试将S
参数指定为S扩展键of(State[R]&{age:number;})
const state = {
foods: {
filter: '',
someForm: {
name: 'Some form',
age: 2
},
someFormWithoutAnAge: {
name: 'other form',
priority: 10
}
}
};
interface HasAge { age: number }
// IMPLEMENTATION
function getForm<O extends {[P in P1]: {[P in P2]: HasAge}}, P1 extends string, P2 extends string>(o: O, p1: P1, p2: P2) {
return (o[p1] as any)[p2] as any;
}
// USAGE
const form1 = getForm(state, 'foods', 'someForm'); // GOOD
const form2 = getForm(state, 'foods', 'someFormWithoutAnAge'); // ERROR
const form3 = getForm(state, 'foods', 'blah'); // ERROR
const form1 = pickAForm((state) => state.foods.someForm);
// ...or...
const form1 = pickAForm(() => initialState.foods.someForm);