是否可以从其通用类型自动生成 class 属性?

Is it possible to auto generate class properties from its generic type?

在 TypeScript 中是否有任何方法可以生成 class 其泛型类型的属性,如下所示:

class SomeClass<T> {
  // Read props from T somehow here?
}

interface Props {
  a: number;
  b: boolean;
}

const obj = new SomeClass<Props>;

// So now both obj.a and obj.b are available in autocomplete with correct types from Props interface

interface Props2 {
  some: string;
  other: number;
  props: boolean;
}

const obj2 = new SomeClass<Props2>;
// Now only three props from Props2 are available to obj2

我不想添加类似

的内容
class SomeClass {
  [prop: string]: any
}

因为它只允许在那里分配任何 属性,我想从通用类型中获得固定列表

类 中不能使用映射类型。但是,在这里构建答案:,您可以创建一个函数来创建一个对象,其定义的属性与这样的接口匹配:

interface Props {
  a: number;
  b: boolean;
}

function build<T>(value?: T): T {
  return Object.assign({}, value);
}


const obj = build<Props>();
// obj contains typed a and b properties

// Or, pass in default values
// const obj = build<Props>({ a: 2, b: false });    

您在这里寻找的是更接近 mixin than standard inheritance. But generic mixins of the interface X<T> extends T variety are not supported by TypeScript 的东西。

您可以创建一个名为 SomeClass 的对象和一个名为 SomeClass<T> 的通用类型,通过某些类型断言,可以通过这种方式使用,但是您 运行 会遇到一些限制。以下是我的做法:

class _SomeClass<T> {
    constructor(t: T) {
        Object.assign(this, t);
    }
    // inside here we don't know about properties of T, though
    // so you'll have to do assertions
    get<K extends keyof T>(k: K): T[K] {
        return (this as any as T)[k]; // assertion
    }
}
type SomeClass<T> = T & _SomeClass<T>;
const SomeClass = _SomeClass as new <T>(t: T) => SomeClass<T>;

class _SomeClass<T> 是通用的,但它本身并不知道实现 T。构造函数将 T 对象中的属性分配给 this(您需要像这样的分配才能在 运行 时获得有效的 T)。在 _SomeClass<T> 实现中,每当您尝试访问 thisT 的任何属性时都需要断言(因此 this as any as Tthis as this & T 是您的朋友)。

那么类型SomeClass<T>定义为_SomeClass<T>Tintersection,那么值SomeClass就是[=31] =] 构造函数,但我们断言它的行为类似于 SomeClass<T> 构造函数。

让我们看看它是否有效:

interface Props {
    a: number;
    b: boolean;
}

const obj = new SomeClass<Props>({ a: 1, b: true });
console.log(obj.a); // 1
console.log(obj.get("a")); // 1

interface Props2 {
    some: string;
    other: number;
    props: boolean;
}

const obj2 = new SomeClass<Props2>({ some: "", other: 2, props: false });

使用您期望的 IntelliSense 进行编译。

当然,仍有局限性。 TypeScript 实际上只允许您 extends classes,其中键名是静态已知的。因此,如果您需要 SomeClass 的通用 subclass,那您就不走运了:

class Nope<T> extends SomeClass<T> { // error!
/* Base constructor return type 'SomeClass<T>' is 
 not an object type or intersection of object types 
 with statically known members. */
}

A concrete subclass 将起作用(只要 keyof T 是静态已知的):

class Okay extends SomeClass<Props> {

}

好的,希望对您有所帮助;祝你好运!

Link to code