I'm defining a class that generically mutates one object type to another, that has a very simple interface: id:string, type:string
I want the class definition to signify that it will return AN assembly and the instantiation to direct WHICH assembly it will return.
Compilation Error (on line 79 return assembly;
):
Type 'Assembly' is not assignable to type 'Out'. 'Assembly' is assignable to the constraint of type 'Out', but 'Out' could be instantiated with a different subtype of constraint '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);
IAssemblyRequirements
and your method promises to return their chosen subtype; but you don't take any inputs which depend on that subtype, and the type parameter itself has no representation at runtime, so the method has no way to actually produce a value of the right subtype. What if somebody creates anew Assembler<IAssemblyRequirements, never>()
, and calls yourassemble
method, which promises in that case to returnnever
? The only way for that to type-check is if you unconditionally throw an exception. – kaya3