在我的 typescript 功能中,我要强制第二个参数的所有键必须属于第一个参数的对象。
与此类似的东西
在此第二个参数的所有键(键和 key2 )必须属于KeyValue对象的键
这里的KeyValue是:
class KeyValue {
key: string;
key2: string;
constructor(k, k2) {
this.key = k;
this.key2 = k2;
}
}
喜欢为此,我实现了mapTo函数
public nest<T, K extends keyof T, K2 extends keyof T>(arr: [T], basis: {[k in K]: {[k2 in K2]}}) {
console.log('Hello!!!');
console.log(basis);
}
该代码可以正常工作,但是如果我在KeyValue类中添加另一个键并在参数中传递该键,则如下所示:和KeyValue到:
class KeyValue {
key: string;
key2: string;
key3: string;
constructor(k, k2, k3) {
this.key = k;
this.key2 = k2;
this.key2 = k3;
}
}
那么我上面实现的功能将无法验证第三把 key 所以我该如何实现上述功能,使其接受动态嵌套值并完美地工作。
一些更多的例子:
最佳答案
您可以使用递归映射类型定义一种结构,该结构允许在每个级别指定T
的任何键。我们还可以通过使用Omit
类型在每个级别上省略当前键来确保在路径中没有两次指定键:
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;
type Nested<T> = { [P in keyof T]?: Nested<Omit<T, P>> | number }
function mapTo<T>(arr: [T], basis: Nested<T>) {
console.log('Hello!!!');
console.log(basis);
}
class KeyValue {
constructor(public key: string, public key1: string, public key3: string) {
}
}
mapTo([new KeyValue('a', 'b', 'c')], { key: 1 }); //-> okay
mapTo([new KeyValue('a', 'b', 'c')], { key: { key1: 1 } }); //-> okay
mapTo([new KeyValue('a', 'b', 'c')], { key1: { key: 1 } }); //-> okay
mapTo([new KeyValue('a', 'b', 'c')], { key1: { key: { key3: 1 } } }); //-> okay
mapTo([new KeyValue('a', 'b', 'c')], { key1: { key: { key4: 1 } } }); //-> error // key4 not exist
mapTo([new KeyValue('a', 'b', 'c')], { key: { key: 1 } }); //-> error, key appears twice