给定以下条件:
class MyClass {}
class MyOtherClass { something!: number; }
type HasClasses = {
foo: MyClass;
bar: string;
doo: MyClass;
coo: {x: string;};
boo: MyOtherClass;
};
type RemovedClasses = RemoveClassTypes<HasClasses>;
我希望RemovedClasses
等于{ bar: string; coo: {x: string;} }
。我该怎么做?
我尝试过我认为有效的方法,但由于某种原因没有成功:
type ClassesKeys<T> = {
[P in keyof T]: T[P] extends new () => any ? P : never;
}[keyof T]
type RemoveClassTypes<T> = Omit<T, ClassesKeys<T>>;
您是说要根据属性是否与类相关来从类型中删除属性,而保留非class
对象类型。这就是为什么在您的示例中要删除foo
和doo
(均为MyClass
(和boo
(MyOtherClass
(,而不是coo
({x: string;}
(。
我认为你做不到。
TypeScript的类型系统是结构化的(基于事物的形状(,而不是标称的状。
例如,看看这个:
class Example {
something: string;
constructor(s: string) {
this.something = s;
}
method(): void {
}
}
let ex1 = new Example("ex1");
let ex2 = {
something: "ex2",
method(): void {
}
};
从类型的角度来看,ex1
和ex2
之间没有区别,尽管在运行时的角度来看有一个微小的区别(ex1
继承了它的method
,而ex2
将它作为自己的属性(。
现在假设您有以下声明:
let ex3: Example;
let ex4: { something: string; method(): void; };
所有这些分配都是有效的:
ex3 = ex1; // Works
ex3 = ex2; // Works
ex4 = ex1; // Works
ex4 = ex2; // Works
ex1 = ex4; // Works
ex2 = ex4; // Works
这些东西的类型都是兼容的。通过class
构造声明的实例类型Example
、从ex2
的对象初始值设定项推断的类型以及分配给ex4
的内联类型,它们都是相互兼容的。
一个转移注意力的问题是类中的对象具有继承的constructor
属性,也许我们可以使用它!但你不能,因为即使是上面的ex2
也有一个继承的constructor
属性(来自Object.prototype.constructor
,即Object
(,而且我认为TypeScript对constructor
属性的处理有点特殊(但不能指向任何文档,可能会出错(。
所以恐怕我不认为你能做你说过你想做的事。