An abstract class is being created here to transform one type of object into another, with a simple interface comprising id:string and type:string.
The intention behind the class definition is to emphasize that it will produce an assembly and during instantiation specify WHICH particular assembly will be generated.
Encountered Compilation Error (at line 79 return assembly;
):
Error: Type 'Assembly' cannot be assigned to type 'Out'. 'Assembly' can be assigned to the constraint of type 'Out', but 'Out' may potentially be instantiated with a distinct subtype of the restriction 'Assembly'.(2322)
Typescript Code:
interface IAssemblyRequirements {
id: string;
type: string;
}
interface IData extends IAssemblyRequirements {
attributes: any;
}
interface IFooBarData extends IData {
attributes: {
start: string;
}
}
interface IBazBarData extends IData {
attributes: {
chickens: number;
}
}
const foobarData: IFooBarData = {
id: "1",
type: "foobar",
attributes: {
start: "Dec 1, 2020"
}
}
const bazbarData:IBazBarData = {
id: "2",
type: "bazbar",
attributes: {
chickens: 9
}
}
class Assembly implements IAssemblyRequirements {
id:string;
type:string;
constructor(data: IData) {
this.id = data.id;
this.type = data.type;
}
}
class FooBar extends Assembly {
start:Date;
constructor(data: IFooBarData) {
super(data);
this.start = new Date(data.attributes.start);
}
}
class BazBar extends Assembly {
chickens: number;
constructor(data: IBazBarData) {
super(data);
this.chickens = data.attributes.chickens;
}
}
const typeAssemblers:{ [key:string]: typeof Assembly } = {
foobar: FooBar,
bazbar: BazBar
}
class Assembler<In extends IData, Out extends Assembly> {
assemble(input: In): Out {
const assembly = new typeAssemblers[ input.type ]( input );
return assembly;
}
}
const assembler = new Assembler<IFooBarData, FooBar>();
const assembly = assembler.assemble(foobarData);