Reputation: 3623
According to typescript documentation, interfaces can extend classes in the following way:
class C {
f1: string;
f2: number;
}
interface I extends C {};
Note that I didn't extend I
with extra members and that's why the body {}
is empty.
The difference between I and C is of course that the plain object { f1: "hi", f2: 3}
conforms to I
but not to C
(because while it has all the fields, it hasn't been produced from C's constructor)
I want to know, is there a type operator that can get I
from C
without having to declare I
? e.g. something like operator<C>
which is equivalent to I
(you could perhaps even use type I = operator<C>
?
Upvotes: 1
Views: 134
Reputation: 812
Depending on your intended use, you might actually be fine just using C
. For example:
class C {
constructor(public f1: string, public f2: number){}
}
interface I extends C {}
function getF1(x: C) {
return x.f1;
}
const x: C = { f1: "abc", f2: 123 };
getF1(x); // returns "abc"
Note when you use C
in a type annotation, Typescript doesn't actually ensure that the object is really an instance of C
, but rather that it has all the properties.
What you wrote isn't really true, that the plain object doesn't "conform" to C
. According to TS type system, it does.
If you had a more complex class and wanted for some reason to do something like get all the attributes but not the methods, you could use a TS mapped type with a conditional type that would return all the properties that are not a function.
In general, it's always worth using the TypeScript Playground to investigate the result of transpilation, to better realize the differences between classes and interfaces in TS.
const sth = { foo: 100 };
const i: I = { f1: "hi", f2: 3};
const fakeC: C = { f1: "hi", f2: 3};
const trueC = new C("h1", 3);
// does it conform to type C at transpilation time?
function ofTypeC(x: C) { return true; }
// ofTypeC(sth); // error
ofTypeC(i); // true
ofTypeC(fakeC); // true
ofTypeC(trueC); // true
// does it conform to type I at transpilation time?
function ofTypeI(x: I) { return true; }
// ofTypeI(sth); // error
ofTypeI(i); // true
ofTypeI(fakeC); // true
ofTypeI(trueC); // true
// is it an instance of class C at run time?
sth instanceof C // false
i instanceof C // false
fakeC instanceof C // false
trueC instanceof C // true
Or perhaps for sth more demonstrative of the caveats for using JS classes as TS types:
class Cat {
public meow() {console.log("meow")}
}
class Dog {
public meow() {console.log("Nah man")}
}
let cat: Cat = new Dog();
cat.meow();
Upvotes: 1