I've forked and edited your code sandbox, check it out:

Now I'm gonna explain a few things about class in typescript, which is indeed quite confusing.
It's in part due to the fact that people use the term "class" to refer to diff things in diff contexts. To disambiguate, let's use more accurate terms.
Constructor
MyPuppy is often called a "class", but it's also a "constructor function" in JS terms. So let's stick to constructor throughout this discussion.
// javascript
class MyPuppy {}
Instance
Variable puppy is an instance of MyPuppet
// javascript
const puppy = new MyPuppet()
Instance Type vs Constructor Type
In typescript, when you declare a class like below, you'll implicitly declare an instance type of the same name!
This behaviour confuses a lot of people. In short, MyPuppy as a JS variable holds a constructor, whereas MyPuppy as a TS type variable actually holds an instance type.
Now how do we refer to the type of MyPuppy constructor, aka the constructor type? You should literally use typeof MyPuppy.
// typescript
class MyPuppet {}
type MyPuppetInstance = MyPuppet
type MyPuppetConstructor = typeof MyPuppet
We've done disambiguating terms, let's do some case study.
There's this concept of the "instance side" and "static side" of a class, once documented in the old TS handbook. Basically "instance side" corresponds to instance type, "static side" to constructor type.
class MyPuppy {
static getSpecies(dog: MyPuppy) {
return dog.species
}
constructor(species: string) { this.species = species }
species: string
// [side note] above two lines can be combined as one:
// constructor(public species: string) {}
poop() { return '💩' }
}
type MyPuppetInstance = MyPuppet
type MyPuppetConstructor = typeof MyPuppet
var bar: MyPuppetConstructor = MyPuppy
var foo: MyPuppetInstance = new bar("shiba_inu")
The above snippet does several things.
- Declare a JS constructor of the name
MyPuppy.
- Implicitly declare a TS instance type
MyPuppy.
- On the "instance side",
foo is an instance, and has a property species and a method poop.
- On the "static side", the
bar is a constructor, it's a "newable function" which can be invoked as new bar("shiba_inu"), and also has a static method getSpecies.
Now in a .d.ts file, how can we declare the above types? You can use either the interface keyword or the type keyword. They make almost no difference.
// index.d.ts
interface MyPuppyInstance {
species: string
poop(): string
}
interface MyPuppyConstructor {
new (species: string): MyPuppyInstance
getSpecies(dog: { species: string }): string
}
type MyPuppyInstance2 = {
species: string
poop(): string
}
type MyPuppyConstructor2 =
(new (species: string) => MyPuppyInstance)
& { getSpecies(dog: { species: string }): string }
CustomClasswhile your js code is forcustomClass(JavaScript IS case sensitive)MyComponent. The type check works fine for the other props, why not with the class? Is it mandatory to extends the class so that inherit the type?ActionProvider.ts. This is where you are defining the ActionProvider class, and there is no link between ActionProvider and yourindex.d.tsfile, so it cannot inherit something you are not referencing at all. If you want your class to infer the types of its variables, you'll need to either doclass ActionProvider extends SomeOtherClassorclass ActionProvider implements SomeInterfacecustomClass: typeof CustomClassin the MyComponentProps definition? If you want to pass the class itself as a value then the type needs to be the type of the constructor not the type of the instance.