I went off the beaten path, at least for me personally in my own landscape, to create a way to use Interfaces as both interfaces and data objects all in one. I'm planning out an NX generator for generating Angular forms with nested reusable form controls from a .ts
file with all the interfaces needed for the data structure they want to use such as the following example
export interface SomeInterface {
propA : string;
propB : number;
propC : SomeOtherInterface;
}
as opposed to
export interface SomeForm {
propA : FormControl< string | null >;
propB : FormControl< number | null >;
propC : FormGroup< SomeFormGroupInterface >;
}
I plan to make the generator generate the latter for them out of the first which brings me to the rabbit hole I wound up going down which is how can I know what to generate from the first one? Would string
be a text field or text area? Would number
be just a number or will it be from a range-input
or maybe a select-input
if they for some niche reason want the user to pick numbers from a drop down. I want it to be simpler than having them make a schema like
{
"propA" : {
"type" : "string",
"controlType" : "text-input",
"defaultValue" : "some value"
},
"propB" : {
"type" : "number",
"controlType" : "counter",
"defaultValue" : 0
},
"propC" : {
"type" : "object",
"controlType" : "group",
"children" : {
/* so on and so on */
}
}
}
Not only does that make it more laborious but what if they decide to make a text-ipnut
rather than a text-input
? They'll now have a massive form to scroll through just for their brain to keep autocorrecting text-ipnut
every time their eyes scan over it. That wouldn't make for a good developer experience.
So I started tinkering around and came up with this idea
// Create type for the different control types.
export type ControlTypes = 'text-field' | 'text-area' | 'number-field' | 'counter'
| 'radio' | 'select' | 'checkbox' | 'range'
| 'group' | 'array';
// Create type for control specs.
export type ControlSpecs = {
control : ControlTypes;
default? : string | number | boolean;
label? : string;
}
// Create interface for spec objects.
export interface ControlSpecObject {
[ prop : string ] : ControlSpecs;
}
// Create interface with single property to apply ControlSpecObject.
export interface ControlData{
_$_controlSpecs : ControlSpecObject;
}
// Then use it with your own interface like this.
export interface YourOwnInterface extends ControlData{
propA : string;
propB : number;
propC : SomeOtherInterface;
_$_controlSpecs : {
propA : {
control : 'text-field';
label : 'Item Name';
};
propB : {
control : 'number-field';
label : 'Quantity';
default : 0;
};
propC : {
control : 'group';
label : 'Some Fieldset'
}
};
}
I have strict mode on and that passes without any erorrs. The thing is, if you do enter something wrong, the red lines will show up on YourOwnInterface
instead of where the error is being made. If you hover over it you'll see which property isn't compatible so you can see where you went wrong but it would be nice if the red lines could show up under the instances of text-ipnut
or number-filed
we may accidentally enter.
So ultimately I want this to be a way to create interfaces that consist of data that also has interfaces applied to it for type checking. I just think it would be more convenient to be able to define both in the same thing. I'm going to be reading the files in the generator so as long as it's valid typescript and doesn't throw any errors I can just make it use the __$__controlSpec
data and strip it out of the final generated files where those same interfaces will be returned back without the __$__controlSpec
object along with all the other files.
Will this be ok so long as it suits the use case or is it a nightmare waiting to happen? Is there some other more proper way I could be doing this or some other thing I'm unaware of that addresses this type of need while being just as simple?
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744662937a4586572.html
评论列表(0条)