typescript - 只接受给定对象的键

标签 typescript typescript-generics

我正在尝试创建一个用对象初始化的 TypeScript 类,并且有一个方法只能将该对象的键作为参数。所以:

class MyClass {
  properties = {};

  constructor(properties) {
    this.properties = properties;
  }

  // Passed propNames should only be keys of this.properties
  pick(...propNames) {
    return propNames.reduce((obj, name) => ({ 
      ...obj, 
      [name]: this.properties[name]
    }), {});
  }
}

这似乎类似于 this problem ,但我不知道如何在这种情况下应用它,因为属性是从外部传入的。

const props = { key: 'value', key2: 'value2' };
interface PropKeys {
  key: string;
  key2: string;
}
type KeyName = keyof(PropKeys);

// But what do I do to the class to get this to work?
const instance = new MyClass(props);
instance.pick('key', 'key2'); // Great
instance.pick('key3'); // Should throw a type error

这可能吗?有没有办法在不显式定义 InstanceKeys 的情况下做到这一点? ,而是从初始化实例时传递的 props 派生它们?

我正在努力研究泛型,并在想可能是这样的:

class MyClass {
  properties = {};

  constructor<Type>(properties: Type) {
    this.properties = properties;
    type TypeKeys = keyof(Type);
  }
  
  pick(...propNames: TypeKeys[]) {
    return propNames.reduce((obj, name) => ({ 
      ...obj, 
      [name]: this.properties[name]
    }), {});
  }
}

但这会引发两种类型的错误:

  • <Type> 上: “类型参数不能出现在构造函数声明中。”
  • TypeKeys[] 上:“找不到名称‘TypeKeys’。” (我的意思是,有道理;这超出了范围。)

更新:这感觉更接近了,但我遇到了一个问题,属性首先在类上定义(在构造函数之上):

class MyClass<PropType extends Properties> {
  properties: PropType = {};

  constructor(properties: PropType) {
    this.properties = properties;
  }

  pick(...propNames: Array<keyof(PropType)>) {
    return propNames.reduce((obj, name) => ({ 
      ...obj, 
      [name]: this.properties[name]
    }), {});
  }
}

我在该行遇到的 TS 错误是

Type '{}' is not assignable to type 'PropType'. '{}' is assignable to the constraint of type 'PropType', but 'PropType' could be instantiated with a different subtype of constraint 'Properties'

这里的问题是任何 properties传入的可能有自己的键,但必须是 Properties 类型的实例,这会限制值。

最佳答案

您的通用类型需要继续 class声明,而不是在其构造函数上。那么keyof Type需要是匿名类型。您还需要输入 properties所以 TypeScript 知道它可以用 keyof Type 索引,我在这个例子中通过给它一个 Partial<Type> 的类型来完成.

我还使用了类型断言,因此初始的 {}你的对象 reduce键入为 Partial<Type> ,因此 TypeScript 将了解如何在创建后对其进行索引。

class MyClass<Type> {
  properties: Partial<Type> = {};

  constructor(properties: Type) {
    this.properties = properties;
  }
  
  pick(...propNames: (keyof Type)[]) {
    return propNames.reduce((obj, name) => ({ 
      ...obj, 
      [name]: this.properties[name]
    }), {} as Partial<Type>);
  }
}

TypeScript Playground

关于typescript - 只接受给定对象的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72252087/

相关文章:

angular - 在服务中使用 ng2-toastr

接受字符串数组并返回以给定字符串作为键的对象的 typescript 函数

typescript - 如何从联合创建类型数组类型

javascript - 在 TypeScript 中使泛型参数的顺序变得多余?

unit-testing - 使用 Webpack、Jasmine (-core)、typescript 进行单元测试

typescript - typescript 可以根据关键条件定义接口(interface)结构吗?

javascript - 如何开 Jest 模拟另一个 react 组件中的函数?

node.js - Typescript TS2339 属性不存在

typescript - 避免在 switch 中进行 typescript 转换

typescript - 联合类型和条件类型的问题