Property * does not exist on type typeof * - static parent method

16.4k Views Asked by At

React Native, TypeScript code JS(non-TS) ORM module:

Parent BaseModel:

export default class BaseModel {
  static createTable() {
    ...
  }
  ...

My model of Animal does NOT redefine the method, it's just defined as:
export default class Animal extends BaseModel { ...

Now this code await Animal.createTable(); actually works, but VSCode TypeScript checker gives following error in code:

Property 'createTable' does not exist on type 'typeof Animal'.ts(2339)

Is this the editor/checker issue? Or should the JS/TS code be defined somehow better?

1

There are 1 best solutions below

0
On

So it seems to be a problem in vscode typescript intelisense not properly analyzing pure JS module (not typescript). Because if I create middl e layer base model in typescript in project it recognizes it just fine. You have to redefine and proxy all used methods to the package parent, but it's still much less painful than adding them to each model.

Optionally, any ts error can be ignored by putting // @ts-ignore BEFORE the line, which I don't recommend if you can avoid it since potentially it could hide important errors.

// @ts-ignore
someLineWithTSerror;

My solution:

AppBaseModel.tsx

import * as SQLite from 'expo-sqlite'
import { BaseModel } from 'expo-sqlite-orm'

export default class AppBaseModel extends BaseModel {
    constructor(obj) {
        super(obj)
    }

    static get database(): any {
        return async () => SQLite.openDatabase('MyAppDemoDB.db')
    }

    static createTable(): Promise<any> {
        return super.createTable();
    }

    static query(options): Promise<any> {
        return super.query(options);
    }

    save(): Promise<any> {
        return super.save();
    }
    // ...

}

Animal.tsx

import { types } from 'expo-sqlite-orm'

import AppBaseModel from 'pathToAppBaseModel/AppBaseModel'

export default class Animal extends AppBaseModel {
    constructor(obj) {
        super(obj)
    }

    static get tableName() {
        return 'animals'
    }

    static get columnMapping() {
        return {
            id: { type: types.INTEGER, primary_key: true }, // For while only supports id as primary key
            name: { type: types.TEXT, not_null: true },
            color: { type: types.TEXT },
            age: { type: types.NUMERIC },
            another_uid: { type: types.INTEGER, unique: true },
            timestamp: { type: types.INTEGER, default: () => Date.now() }
        }
    }
}

Example test usage

import { useEffect } from 'react';
import { Alert } from 'react-native';
import Animal from 'pathToAnimal/Animal'

// ... const SomeComponent = ({navigation}) => { ...

useEffect(() => {

    const testDB = async () => {
        await Animal.createTable();

        const props = {
            name: 'Bob',
            color: 'Brown',
            age: 2
        };

        const animal: Animal = new Animal(props);
        const save_result = await animal.save();
        let X_TEST = await Animal.query({
            columns: 'id, name',
            page: 1,
            limit: 30,
        });
        //X_TEST = [animal, save_result];
        Alert.alert ("X", JSON.stringify(X_TEST, null, 2));
    };
    testDB().catch(console.error);

});