注意:我已经更新了这个问题,希望能让事情更清楚。
我试图通过名为elemTypes
的代理对象来实例化类。此对象是我要用于基于类似DOM的树结构以编程方式构建对象的类的引用列表。我是TypeScript的新手,所以我希望我在这里只是缺少一些简单的东西?
以下是代码:
type elemDef = {
type: string,
name: string,
childNodes: object[]
}
class Elem {
childNodes: object[]
constructor (childNodes: object[]) {
this.childNodes = childNodes
}
}
class Div extends Elem {
constructor (childNodes: object[]) {
super(childNodes)
}
}
class Form extends Elem {
constructor (childNodes: object[]) {
super(childNodes)
}
}
class Input extends Elem {
name: string
constructor (childNodes: object[], nodeDef: elemDef) {
super(childNodes)
this.name = nodeDef.name
}
}
const div = {
type: 'Div',
childNodes: [
{
type: 'Form',
childNodes: [
{
type: 'Input',
name: 'username',
childNodes: []
},
{
type: 'Input',
name: 'password',
childNodes: []
},
]
}
]
}
// I expect that I am doing this part wrong:
const elemTypes = {
Div,
Form,
Input
}
const makeElem = (nodeDef: elemDef) => {
const childNodes:object[] = []
nodeDef.childNodes.forEach((childNodeDef: object): void => {
const element = new elemTypes[childNodeDef.type](childNodeDef)
childNodes.push(element)
})
const element = new elemTypes[nodeDef.type](nodeDef)
return element
}
// This line just demonstrates that the code is working:
console.log(JSON.stringify(makeElem(div), null, 2))
上面一行的输出是:
{
"childNodes": {
"type": "Div",
"childNodes": [
{
"type": "Form",
"childNodes": [
{
"type": "Input",
"name": "username",
"childNodes": []
},
{
"type": "Input",
"name": "password",
"childNodes": []
}
]
}
]
}
}
我遇到的问题是,SublimeText 3给了我这个错误:
Element implicity has a type 'any' type because the type
'{ Div: typeof Div; Form: typeof Form; Input: typeof Input };
has no index signature;
我试过通过阅读TypeScript文档并查看类似问题的一些StackOverflow答案来解决这个问题,但我似乎无法找到我在这里做错了什么。
但是有没有人知道是否有办法定义meta
对象将停止在我的IDE中隐藏任何错误? (注意:我不想在我的.ts-config.js
文件中关闭隐式错误。)
我不想在ts-config
。{/ p>中关闭任何隐含的规则
任何想法都赞赏。
答案 0 :(得分:1)
它在javascript中运行,因此必须使用( 更多 错综复杂的 方式)打字稿。
如果"我不知道你想要达到的目标,但这就是你如何做到的!" 看起来是一个可接受的答案开始,继续阅读。
在解决主要问题之前,请执行以下所有更改。
//Be specific. Change all the "object" type annotations to "elemDef". Doing
//so, the compiler will be able to validate if the type of an argument you are
//trying to pass to your constructors contains all the properties existent
//in an "elemDef" object.
type elemDef = {
type: string;
name?: string; //<- not all elements have a name, make it optional
childNodes: elemDef[]; //<- you have a recursive structure.
}
class Elem {
readonly type: string;//<- the type of an element is not supposed to change
childNodes: elemDef[];
constructor (childNodes: elemDef[]) {
this.childNodes = childNodes;
this.type = "Elem";
}
}
class Div extends Elem {
readonly type: string;
constructor (childNodes: elemDef[]) {
super(childNodes);
this.type = "Div";
}
}
class Form extends Elem {
readonly type: string;
constructor (childNodes: elemDef[]) {
super(childNodes);
this.type = "Form";
}
}
输入构造函数中 nodeDef 的参数类型必须为 elemDef &amp; < em> { name : string } 所以它不会接受为参数任何没有名称的elemDef。
class Input extends Elem {
readonly type: string;
name: string;
constructor (childNodes: elemDef[], nodeDef: elemDef & { name : string }) {
super(childNodes);
this.name = nodeDef.name;
this.type = "Input";
}
}
那么,还有什么遗漏?
这是对象的索引签名:
{ [key: type1]: type2 }
编译器推断 elemTypes 的类型为:
const elemTypes: {
Div: typeof Div;
Form: typeof Form;
Input: typeof Input;
}
因此有必要提供一个从字符串映射到函数的签名,但是当你这样做时,编译器会告诉你可以使用 new 运算符来调用一个函数缺少构造函数签名。从第二个问题开始:
//this is a type that defines a signature for a generic constructor for elements
type ElementConstructor<T> = {
new(childNodes: elemDef[]): T;
}
现在我们提供签名并使用 ElementConstructor 类型来转换 const elemTypes 中的每个类:
const elemTypes : { [index: string]: ElementConstructor<Elem> } = {
Div: Div as ElementConstructor<Div>,
Form: Form as ElementConstructor<Form>,
Input: Input as ElementConstructor<Input>
};
最后
只需在 makeElement 函数中进行一些调整:
// In your original snippets, you were passing objects to constructor in
// the forEach but all your constructors take arrays as arguments
const makeElem = (nodeDef: elemDef) => {
const childNodes: elemDef[] = [];
nodeDef.childNodes.forEach((childNodeDef: elemDef): void => {
const element = new elemTypes[childNodeDef.type]([childNodeDef]); // <- put inside an array
childNodes.push(element);
});
const element = new elemTypes[nodeDef.type]([nodeDef]); //<- put inside an array
return element;
}
答案 1 :(得分:-1)
不完全确定,但也许你可以尝试这样的事情并看看它是否有帮助?
const proxy: {person: Being} = {
person: Being
}