Let's say we have an enum, "Profession":
enum Profession {
Teacher = "Teacher",
Scientist = "Scientist",
Rapper = "Rapper",
}
And we have a Person
interface, which accepts a generic drawn from Profession
's values:
interface Person<P extends Profession> {
profession: P;
}
And finally, we want to implement Person
:
class AmericanCitizen implements Person<Profession.Teacher> {
// ... problem continued below
}
... within the class implementation, I'd like to assign the generic-specified profession
like so:
class AmericanCitizen implements Person<Profession.Teacher> {
profession = Profession.Teacher;
}
This results in the following TS error:
Property 'profession' in type 'AmericanCitizen' is not assignable to the same property in base type 'Person<Profession.Teacher>'.
Type 'Profession' is not assignable to type 'Profession.Teacher'.
The compiler forces me to do the long-hand equivalent:
class AmericanCitizen implements Person<Profession.Teacher> {
profession: Profession.Teacher;
constructor() {
this.profession = Profession.Teacher;
}
}
Why is it that the former is invalid?
class AmericanCitizen implements Person<Profession.Teacher> {
profession = Profession.Teacher;
}
Since you haven't told typescript what type you want profession
to be, typescript will try to infer it from how you're using it. It sees you're assigning Profession.Teacher
to it, which is part of an enum so it assumes you want profession
to be that enum. Not a specific value of the enum though; the whole thing. Similarly if you tried to define name = "bob"
it would assume you wanted string
as the type, not specifically "bob", and age = 100
would be number
, not specifically 100.
You can tell typescript that you want something more specific in several ways:
profession: Profession.Teacher = Profession.Teacher;
profession = Profession.Teacher as Profession.Teacher;
profession = Profession.Teacher as const;
Your version with a constructor works too and is equivalent to my first example.