Premium support for our pure JavaScript UI components


Post by pmiklashevich »

Hi! Could you please suggest how to declare field types in a model class when you extend Model?
I get typings error when I refer to fields as this.myField.

Property 'myField' does not exist on type 'MyModel'.

For example:

import { Model, DataFieldConfig } from '@bryntum/schedulerpro'

class PlayerModel extends Model {
  static $name = 'PlayerModel'

  static get fields(): Partial<DataFieldConfig>[] {
    // [TypeScript] Property type is missing in DataFieldConfig #5017
    // https://github.com/bryntum/support/issues/5017
    return [
      { name: 'firstName', type: 'string', dataSource: 'first_name' },
      { name: 'lastName', type: 'string', dataSource: 'last_name' },
    ]
  }

  get isPlayerModel(): boolean {
    return true
  }

  get fullName(): string {
    // TODO: think how to declare 'firstName' and 'lastName'.
    //       Property 'firstName' does not exist on type 'PlayerModel'.
    //       Property 'lastName' does not exist on type 'PlayerModel'.
    return `${this.firstName} ${this.lastName}`
  }

  set fullName(name: string) {
    const [firstName, ...otherNames] = name.split(' ')
    const lastName = otherNames.join(' ')

this.firstName = firstName
this.lastName = lastName
  }
}

export default PlayerModel
Снимок экрана 2022-08-10 в 15.49.30.png
Снимок экрана 2022-08-10 в 15.49.30.png (288.14 KiB) Viewed 729 times

Thanks in advance!

Pavlo Miklashevych
Sr. Frontend Developer


Post by saki »

Pavel, you can add:

    public firstName = '';
    public lastName = '';

to the PlayerModel class. That will resolve the TS errors but I haven't tested whether it'll actually work in the app. I see no reason why it shouldn't, though. Let us please know if it helped.


Post by pmiklashevich »

Hello Saki!

It doesn't work. When you specify classes like this, you give it priority over the real fields. So the grid has empty rows.

  public firstName = 'Peter';
  public lastName = 'Parker';

The value you set is spread around the grid

Снимок экрана 2022-08-11 в 11.03.22.png
Снимок экрана 2022-08-11 в 11.03.22.png (29.25 KiB) Viewed 697 times

Pavlo Miklashevych
Sr. Frontend Developer


Post by saki »

I see. Let's try to be less forceful then:

    public firstName!: string;
    public lastName!: string;

Mind the exclamation mark.


Post by pmiklashevich »

Hello Saki,

This approach doesn't work either. The values are undefined. Please get one of your examples up and running and try it yourself. Need to come up with a proper solution to be able to define types for new fields. I would appreciate your help on this.

Thanks!

Pavlo Miklashevych
Sr. Frontend Developer


Post by pmiklashevich »

Hi again! I think I have found a solution. Please take a look and let me know what you think. If you find it useful please update the docs accordingly.

I was inspired by lib.d.ts docs. It shows how to customise Window object. I also found a reference to TS docs. Trying to understand the difference between "type" and "interface" declaration, I found the following StackOverflow thread. The answer shows all possible combinations to extend interfaces/types. Also the difference is highlighted in official TS docs.

So, here is the solution. You can see it solves two problems. First, it adds declaration to the fields described in the "fields" static getter. Second, it adds missing "type" property to the DataFieldConfig type (there was another report to add the "type" https://github.com/bryntum/support/issues/5017). But now this can be a workaround for those who spot a type is missing. Previously the suggestion was to use ts-ignore which actually masked the problem.

import { Model, DataFieldConfig } from '@bryntum/schedulerpro'

// Implicitly adds new fields to an existing interface (mixes types into PlayerModel extending Model types)
interface PlayerModel {
  firstName: string;
  lastName: string;
}

// Explicitly extends Bryntum types and adds missing types
interface DataFieldConfigExtension extends DataFieldConfig {
  type: string;
}

class PlayerModel extends Model {
  static $name = 'PlayerModel'

  static get fields(): Partial<DataFieldConfigExtension>[] {
    return [
      { name: 'firstName', type: 'string', dataSource: 'first_name' },
      { name: 'lastName', type: 'string', dataSource: 'last_name' },
    ]
  }

  get isPlayerModel(): boolean {
    return true
  }

  get fullName(): string {
    return `${this.firstName} ${this.lastName}`
  }

  set fullName(name: string) {
    const [firstName, ...otherNames] = name.split(' ')
    const lastName = otherNames.join(' ')

this.firstName = firstName
this.lastName = lastName
  }
}

export default PlayerModel

See, no TS errors in IDE:

Screen Shot 2022-08-20 at 21.03.23.png
Screen Shot 2022-08-20 at 21.03.23.png (305.74 KiB) Viewed 625 times

Best regards!

Pavlo Miklashevych
Sr. Frontend Developer


Post by sergey.maltsev »

Hi, Pavel.

Yes you are right.
We actually have pretty much the same code in our Gantt Angular Advanced demo in Gantt/examples/frameworks/angular/advanced/src/app/lib/Task.js

I've created this issue to add some clarification for this approach to Docs guides.
https://github.com/bryntum/support/issues/5106


Post by pmiklashevich »

Hi Sergey! Thanks for confirming I'm right!
Cheers!

Pavlo Miklashevych
Sr. Frontend Developer


Post Reply