typescript - Är det möjligt att definiera en klass som implementerar ett gränssnitt utan implementation?


Är det möjligt att definiera en klass som har gränssnittsvariabler utan implementation i TypeScript?

Till exempel:

interface ITask {
  id: number;
  title: string;
}

class Task implements ITask {
  // without implementation
}

Koden ovan kommer att orsaka ett fel som detta:

Type 'Task' is missing the following properties from type 'Task', ...

Jag försökte också följande kod, men den orsakade också ett fel:

class Task extends ITask {
  // without implementation
}
TypeError: Class extends value undefined is not a constructor or null

Jag ställer denna fråga eftersom jag vill generera klasser från gränssnitt automatiskt, utan att ändra några variabler. Jag vill inte kopiera och klistra in alla variabler.

Svar #1

Det finns mycket typkontroll som --strict-sviten av kompilatoralternativ ger dig. (Om du inte använder den, bör du göra det.) Det låter som att du försöker kringgå en del av den och det är inte klart för mig varför du vill göra detta. Om du övertygar kompilatorn om att klassen har implementerat gränssnittet utan att faktiskt göra det, gör du bara att kompilatorvarningar som är avsedda att förhindra körfel undertrycks. Som det står, producerar följande kod kompilatorvarningar:

const t: ITask = new Task(); // error here
t.id.toFixed(2); 

vilket är en bra sak, eftersom vid körning kommer t.id att vara undefined, så t.id.toFixed() kommer att kasta ett undantag. Om du tvingar Task implements ITask att fungera, skulle du inte få några kompilatorvarningar, men du skulle fortfarande få ett körfel.


Om du verkligen vill göra detta kan du använda deklarationssammanfogning för att återöppna Task:s instansgränssnitt och låta det utvidga ITask:

interface Task extends ITask { } // merging
class Task implements ITask {
}

Nu finns det inget fel, men naturligtvis stöter du på samma problem här:

const t = new Task();
t.id.toFixed() // compiles without error

Om du vill vara säker kan du låta Task implementera Partial<ITask> genom att använda hjälptypen Partial<T> för att göra egenskaperna från ITask valfria:

interface Task extends Partial<ITask> { }
class Task implements Partial<ITask> {
}

Och nu kommer kompilatorn att förvänta sig att en Task möjligen har dessa fält, men du behöver kontrollera dem för nullvärden innan du använder dem, till exempel genom att använda den valfria kedjeoperatorn (?.):

const t = new Task();
t.id.toFixed() // compiler error now
t.id?.toFixed(); // okay

Playground-länk till kod

Svar #2

Du kan använda detta tillvägagångssätt

interface IUser {
  name: string;
  email: string;
  phone: string;
}

interface User extends IUser {}
class User {
  constructor(user: IUser) {
    Object.assign(this, user);
  }

  getFullName() {
    return this.name;
  }
}

const userData: IUser = {
  email: "[email ",
  phone: "1234567890",
  name: "John Doe",
};

const user = new User(userData);
console.log(user.email); // [email 
console.log(user.getFullName()); // John Doe

Relaterade artiklar