7

Is it possible to reference current class type in type signature? so that I can do something like this:

 export class Component{
  constructor(config?: { [field in keyof self]: any }) {
      Object.assign(this, config)
  }
}

the idea is to pass a configuration object that would consist of current class keys.

I could go with interfaces but then I need to type same portion of code twise (in interface and in implementing class)

Another way would be to use generics. Something like this:

export class Component<T>{
  init(config?: { [field in keyof T]?: any }) {
    Object.assign(this, config)
  }
}

class TestComponent extends Component<TestComponent>{
  foo: number
}
const component = new TestComponent().init({ foo: 11 })

But having code like class TestComponent extends Component<TestComponent> makes me to search for better ways...

4
  • Isn't it allowed to write ‘keyof Component‘? Or am I misunderstanding your question? Commented Nov 3, 2018 at 15:13
  • 1
    You can, but not in the constructor, you can use this as a type. github.com/Microsoft/TypeScript/pull/4910 Commented Nov 3, 2018 at 15:16
  • @TitianCernicova-Dragomir, wow, cool. This should be an answer. Having this not in constructor is completely fine for me. This is event better to make such kind of things somewhere in init function, since constructor runs before default values are set up. Commented Nov 3, 2018 at 15:32
  • @SET just added it as an answer :) Commented Nov 3, 2018 at 15:33

2 Answers 2

12

You can reference the current class using polymorphic this type

export class Component{
  init(config?: { [field in keyof this]?: this[field] }) {
    Object.assign(this, config)
  }
}

class TestComponent extends Component{
  foo: number
}
const component = new TestComponent().init({ foo: 11 })
const component2 = new TestComponent().init({ foo: "11" }) // err

You can't however use this as a type in the constructor

export class Component{
  constructor(config?: { [field in keyof this]?: this[field] }) { // error
    Object.assign(this, config)
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

worse to mention than one should not even want to do such kind of things in constructor, because default values that class may have, would be populated AFTER constructor execution and, such, would overwrite assignment from config object.
-2

Doesn't this just work?

export class Component {
  test = 123;

  constructor(config?: { [field in keyof Component]: any }) {
      Object.assign(this, config)
  }
}


new Component({ test: 123 }) // valid
new Component({ test1: 123 }) // invalid

Playground

Even shorter would be simple (thanks to duck typing)

constructor(config?: Component) {

Maybe not really expressing what you want to say / not strict enough, but works.

Even the following is valid

constructor(config = <Component>{}) {

which directly gives you an empty object as the initial value.

Source: abusing this since TypeScript v1.

6 Comments

In future, I want hundreds of different components which extends basic Component so I should refer to current class, some kind of this, not to basic Component
what does it change? export class ChildComponent extends Component { constructor(config?: ChildComponent ) { super(config); }}
It should work, but going this way, I have to redefine constructor every time in each inherited class. Accepted answer show better solution.
Why do you need to redefine constructor? I do not see any problem anyway. Please post what is not working with this solution
it is working but if you will have some classes that will inherit from Component and if you would need to have their properties to be assignable withing config object, then you have to redefine constructor in each such class as you showed previously in example with ChildComponent class.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.