javascript - 强制函数的参数必须属于泛型类型 T

标签 javascript typescript generics

在我的 typescript 函数中,我想强制第二个参数的所有键必须属于第一个参数的对象。

类似的东西

mapTo([new KeyValue('a', 'b'), new KeyValue('x', 'y')], {key: {key2: 1}});

在此第二个参数的所有键(keykey2)必须属于 KeyValue 对象的键

这里的键值是:

class KeyValue {
  key: string;
  key2: string;

  constructor(k, k2) {
    this.key = k;
    this.key2 = k2;
  }
}

喜欢

mapTo([new KeyValue('a', 'b')], {key: {key2: 1}}); -> ok

mapTo([new KeyValue('a', 'b')], {key: {key3: 1}}); -> error // invalid key3

为此我实现了 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 类中添加另一个键并将此键传递到参数中,如下所示:

mapTo([new KeyValue('a', 'b' ,'c')], {key: {key2: {key3: 1}}});

和 KeyValue 到:

class KeyValue {
  key: string;
  key2: string;
  key3: string;

  constructor(k, k2, k3) {
    this.key = k;
    this.key2 = k2; 
    this.key2 = k3;
  }
}

然后我上面实现的函数不会验证第三个 key

那么我怎样才能实现上述功能,使其接受动态嵌套值并完美地工作。

更多例子:

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')], {key3: {key2:0}); -> okay

最佳答案

您可以使用递归映射类型来定义一个结构,该结构允许在每个级别指定 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 

关于javascript - 强制函数的参数必须属于泛型类型 T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49350891/

相关文章:

javascript - Angular 2 与 TypeScript : View not updating after setting variable in response handler

javascript - Angular:跨字段验证不适用于 setError()

typescript - REST - 强类型模型

java - 将方法泛型类型传递给内部调用

c# - 为泛型类中的静态方法设置无类型

javascript - Excel VBA - 更改 Javascript 函数的值(无参数)

javascript - 如何在页面加载或刷新时打印或回显随机 php 字符串?

Javascript - 如何更改动画的持续时间 onclick

java - 提取具有通用返回类型的表达式后类型不匹配

javascript - ASP.NET MVC JSON Entity Framework - 保存数据