TypeScript中是否可以通过其通用类型生成具有如下属性的类:
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
}
因为它将只允许在此处分配任何属性,而我想从泛型类型获得固定列表
答案 0 :(得分:2)
您在这里寻找的是比标准继承更接近mixin的东西。但是interface X<T> extends T
种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>;
类_SomeClass<T>
是通用的,但本身并不知道实现T
。构造函数将T
对象中的属性分配给this
(您需要类似此分配的内容才能在运行时获取有效的T
)。在_SomeClass<T>
实现内部,每次尝试访问T
上this
的任何属性时都需要声明(因此this as any as T
或this as this & T
是您的朋友)。
然后将类型SomeClass<T>
定义为_SomeClass<T>
和T
的{{3}},然后值SomeClass
就是_SomeClass
构造函数,但我们断言它的作用类似于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
个类,其中的键名是静态已知的。因此,如果您需要SomeClass
的通用子类,那么您就不走运了:
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. */
}
一个具体的 子类将起作用(只要静态知道keyof T
即可):
class Okay extends SomeClass<Props> {
}
好的,希望能有所帮助;祝你好运!
答案 1 :(得分:0)
映射的类型不能在类中使用。但是,在这里建立答案:https://stackoverflow.com/a/48345383/626911,您可以创建一个函数来创建一个对象,该对象的定义的属性与如下接口相匹配:
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 });