Reputation: 1338
I have an injectable Class<T extends { [key: string]: any }>
which has the purpose of obtaining a Generic Object. Such as:
interface Home {
darkTheme: boolean;
userType: number;
}
and then I would inject my class like:
constructor(myClass: Class<Home>) {}
this works great for some methods that live inside my class. However, I want the class to be aware that its body has the keys of T as properties also. In a way that this:
const userType = this.myClass.userType // acknowledges it exists
is ok by typescript.
TS doesn't throw an error with this, and userType
would get the desired value. But this happens with Typescript being ignorant that the property exists in the body of myClass
.
So how can I tell Typescript that myClass<T>
has a body T
?
I have tried:
class myClass<T extends { [key: string extends keyof T]: any}> // nope
class myClass<T extends { [key: string]: any } implements/ extends T> // also nope
// I tried overloading
interface myClass<T extends { [key: string]: any }> {
[key: K keyof T]: T[K]; // don't know what 'K' is;
}
interface myClass<T extends { [key: string]: any }> {
[key: keyof T]: T[keyof T]; // interfaces don't like mapped types
}
and little more. If you have any idea how can I achieve this, or if it's possible at all, I'd be happy to read you! :D thanks.
Upvotes: 2
Views: 2254
Reputation: 250106
Typescript does not support extending the type parameter directly. Depending on what you are trying to do, you can either use a type alias:
type Class<T> = T & {}
declare let myClass: Class<Home>
myClass.userType // works, and is checked
myClass.userTypes // err
Or you can define your class without the explicit T
and then cast it as a constructor that returns something that also has the properties of T
:
class _Class {
m() { }
}
const Class = _Class as (new <T>() => _Class & T);
type Class<T> = T & _Class
let myClass = new Class<Home>()
myClass.m(); //ok
myClass.darkTheme // ok
Upvotes: 3