Egenskapen '' finns inte i typen '' när man använder en klass som returneras av en funktion i TypeScript
Jag har en funktion i TypeScript som returnerar en klass. Sedan används den returnerade klassen för att utöka en ny klass. Syftet här är att byta ut utgångsklassen mellan två inmatningsklasser beroende på en extern trigger och sedan exportera klassen.
Men när jag försöker använda utdata-klassen för instansiering eller skapa en annan klass genom utvidgning, genererar typkontrollern ett fel som indikerar att egenskaperna inte finns när jag försöker få åtkomst till klassens egenskaper.
Property 'name' does not exist in type 'class1'"
I alla fall körs koden och jag får det förväntade resultatet.
Istället, när jag skapar en klass som ärvts från en av de ursprungliga klasserna, finns det inget fel från typen. Så problemet verkar orsakas av klassen som returneras av funktionen.
Här är ett exempel på kod (För tydlighetens skull replikeras det rapporterade problemet i denna kod men det är inte den ursprungliga. Bara för att upprätthålla sekretess. I den slutliga implementeringen kan c1 och c2 skilja sig mer, variabeln "type" ändras och "class1" exporteras. Därför letar jag efter en metod för att dynamiskt specificera klassen)
// CLASS client1
class c1 {
name: string
location: string = "paris"
constructor(name: string){
this.name = name
this.output()
}
handle(){}
process(): string {
let value = this.output()
return value
}
protected output(): string{
return this.name+":"+this.location
}
}
// CLASS client2
class c2 {
name: string
location: string = "tokyo"
constructor(name: string){
this.name = name
this.output()
}
handle(){}
process(): string {
let value = this.output()
return value
}
protected output(): string{
return this.name+"->"+this.location
}
}
// CLASS selector
let type = "c2"
function selector(){
if (type == "c2"){
return c2
}
else{
return c1
}
}
// CLASS作成
class class1 extends selector(){}
const member = new class1("jhon",1)
// (typechecker Error: Property 'name' does not exist in type 'class1'")
console.log(member.name)
// (typechecker Error: Property 'process' does not exist in type 'class1'")
class class2 extends class1{
handle(){
return this.process()
}
}
const member2 = new class2("juan",1)
console.log(member2.handle())
Förresten, vid instansiering kan jag lösa felet genom att ställa in gränssnittet.
interface base extends c1{}
const member = new class1("juan",1) as base
Men när det gäller att skapa en annan klass med "extends" kan jag inte hitta hur jag ska gå tillväga för att koppla gränssnittet.
Kan jag få några råd om hur man löser denna inkonsekvens efter klassretur, eller om hur man byter mellan två klasser? Jag uppskattar din hjälp.
Här är en länk till felet i TypeScripts lekplats
Svar #1
Det du gör är ganska förvirrande. Du verkar försöka specificera dynamiskt vilken klass som ska ärvas. Men det finns bara någonsin en class1, det du har skapar varken c1 eller c2 dynamiskt eftersom den klass-satsen bara tolkas en gång.
Jag tror att du letar efter en fabrikfunktion:
class c1 {
name: string
location: string = "paris"
constructor(name: string){
this.name = name
this.output()
}
handle(){}
process(): string {
let value = this.output()
return value
}
protected output(): string{
return this.name+":"+this.location
}
}
// CLASS client2
class c2 {
name: string
location: string = "tokyo"
constructor(name: string){
this.name = name
this.output()
}
handle(){}
process(): string {
let value = this.output()
return value
}
protected output(): string{
return this.name+"->"+this.location
}
}
let type = "c2"
function createC(name: string) {
if (type == "c2"){
return new c2(name);
}
else{
return new c1(name);
}
}
const member = createC("john")
// Works
console.log(member.name);
Ovanstående är fortfarande lite osäkert. Det känns som att du borde ha en basklass för c1 och c2 och createC bör alltid returnera typen av basklassen. Med det sagt, på grund av TS-inferens och duck-typing, bör ovanstående kod fungera på ett liknande sätt som att använda en basklass.
Utan att överanalysera ditt exempel är den enda skillnaden mellan båda klasserna platsen. Observera också att du bör undvika att utföra något arbete i konstruktörer. Här är mitt förslag.
abstract class c {
abstract location: string;
constructor(public name: string) {}
protected output(): string {
return `${this.name} -> ${this.location}`;
}
process(): string {
return this.output();
}
}
class c1 extends c {
location: string = "paris"
}
class c2 extends c {
location: string = "tokyo";
}
let type = "c2"
function createC(name: string): c {
return type === "c2" ? new c2(name): new c1(name);
}
const member1 = createC("jean");
console.log(member1.process());
type = "c1";
const member2 = createC("ジョン");
console.log(member2.process());
