realm-js icon indicating copy to clipboard operation
realm-js copied to clipboard

Typescript realm types return RealmObject not their original type

Open Genhain opened this issue 5 years ago • 11 comments

Goals

Using Typescript i am attempting to use RealmJS and retrieve some objects after persisting them

Expected Results

when i fetch the results they are of the type i defined them as in this case 'Party'

Actual Results

they are RealmObject instead of my Party type

Steps to Reproduce

Use the format of the code below

Code Sample

Party type

import { NameBadge } from '../interfaces/NameBadge'
import { WalkInConfig } from '../interfaces/WalkInConfig'
import { Grouping } from '../interfaces/Grouping'
import { Survey } from '../interfaces/Survey'
import { NamecardQuota } from '../interfaces/NameCardQuota'
import { Question } from '../interfaces/Question'
import { Expose } from 'class-transformer'
import getRealm from './realm'

export class Party {
	id!: number
	name!: string
	@Expose({ name: 'start_at' })
	startAt!: Date
	@Expose({ name: 'end_at' })
	endAt!: Date
	place?: string | null
	details?: string | null
	logo!: string
	@Expose({ name: 'logo_bnw' })
	logoBnw!: string
	@Expose({ name: 'name_badge' })
	nameBadge!: NameBadge
	@Expose({ name: 'name_badges' })
	nameBadges!: NameBadge[]
	@Expose({ name: 'attendee_ids' })
	attendeeIds!: number[]
	@Expose({ name: 'grouping_ids' })
	groupingIds!: number[]
	@Expose({ name: 'updated_at' })
	updatedAt!: Date
	@Expose({ name: 'created_at' })
	createdAt!: Date
	@Expose({ name: 'custom_attendee_field_names' })
	customAttendeeFieldNames!: string[]
	@Expose({ name: 'walk_in_config' })
	walkInConfig!: WalkInConfig
	@Expose({ name: 'updated_attendee_ids' })
	updatedAttendeeIds!: number[]
	@Expose({ name: 'attendee_custom_line_1' })
	attendeeCustomLine1?: string | null
	@Expose({ name: 'attendee_custom_line_2' })
	attendeeCustomLine2?: string | null
	questions!: Question[]
	groupings!: Grouping[]
	surveys!: Survey[]
	@Expose({ name: 'namecard_quota' })
	namecardQuota!: NamecardQuota
	static schema: Realm.ObjectSchema

	static parties(): Party[] {
		console.log(getRealm().objectForPrimaryKey(Party.schema.name, 34)) // returns RealmObject rather than 
		return Array.from(getRealm().objects<Party>(Party.schema.name))
	}

	static persist(party: Party) {
		console.log(Party)
		getRealm().write(() => getRealm().create(Party.schema.name, party))
	}

	get stuff() {
		console.log("sup")
		return 'hey there'
	}

	set stuff(val: String) {
		
	}
}

Party.schema = {
	name: 'Party',
	primaryKey: 'id',
	properties: {
		id: 'int',
		name: 'string',
		startAt: 'date',
		endAt: 'date',
		place: 'string?',
		details: 'string?',
		logo: 'string',
		logoBnw: 'string',
		attendeeIds: 'int[]',
		groupingIds: 'int[]',
		updatedAt: 'date',
		createdAt: 'date',
		customAttendeeFieldNames: 'string[]',
		updatedAttendeeIds: 'int[]',
		attendeeCustomLine1: 'string?' ,
		attendeeCustomLine2: 'string?'
	}
}

realm.js file for holding shared instance

import { Party } from './Party'
import { Test } from './test'
import Realm from 'realm'

let realmInstance: Realm | null

const getRealm = (): Realm => {
	if (realmInstance == null) realmInstance = new Realm({ schema: [ Party.schema, Test] })
	return realmInstance!
}

export default getRealm

snippet of me using RealmJS in a component

try {
	let existingParties: Party[] = Party.parties()
	console.log(existingParties)
	if (existingParties.length == 0) {
		let fetchParties = await fetch(path, {
			headers: {
				Authorization: `Bearer ${this.accessToken}`
			}
		})

		let responseJson = await fetchParties.json()
		let parties: Party[] = responseJson.parties.map( (x: any) => plainToClass(Party,x) )
		parties.forEach(x => Party.persist(x))

	} else {
		this.partiesFetcher.next(existingParties.map(x => new Party(x))) // this function expects Party Type but get's RealmObjects and has a hissy fit.
	}
} catch (e) {
	console.log(e)
}

And to confirm the behaviour i wrote a quick 'Test.js' class

import Realm, { ObjectSchema } from 'realm'

export class Test {
 
  get stuff()   {
    return "hello"
  }

  set stuff(val) {

  }
}

Test.schema = {
  name: 'Test',
    primaryKey: 'id',
    properties: {
      id: 'int',
      name: 'string'
    }
}

snippet attempting to retrieve Test type

let object = getRealm().objectForPrimaryKey('Test',123)
console.log(object)
if (object == null){
	getRealm().write(() => {
		getRealm().create(Test.schema.name, {id: 123, name: "steve"})
	})
}

This prints a Test type in the console and further more has the stuff method, the Party or RealmObject does not contain the defined methods.

Here is an repo project detailing what i am referring to

Version of Realm and Tooling

  • Realm JS SDK Version: "^2.26.1"
  • Node or React Native: "0.59.4"
  • Client OS & Version: Mojave 10.14.5
  • Which debugger for React Native: ? React Native Debugger

Genhain avatar May 31 '19 12:05 Genhain

#536 This guy opted to pass the returned object into the type constructor to finish the job, although he appears to using vanilla JS and is getting issues. i am using typescript. Of course i can do this, but would like to see if we can address this if possible.

Genhain avatar Jun 01 '19 06:06 Genhain

When I run your app, I get:

[ { id: 4, name: 'abc' } ]
[ { id: 1, name: 'a' }, { id: 2, name: 'b' } ]

I agree that we should take a closer look at our TypeScript support and improve it.

kneth avatar Aug 19 '19 11:08 kneth

Any progress on this? Or any hints what can cause the issue? It did work for me but is biting me right now. I upgraded dependencies and suddenly realm returns RealmObjects instead of class instances.

The weird thing is that i actually did not upgrade realm itself ([email protected]) but bunch of other dependecies (react, babel, expo etc). There is also no library between my code and my calls to realm. Trying to figure out what is happening.

giniedp avatar Aug 03 '20 09:08 giniedp

RealmObjects are created, whenever the constructor for given name could not be found (obviously).

It happens here https://github.com/realm/realm-js/blob/8c32a4c9c6bc1876dca8442d42291bae37739ff4/lib/browser/objects.js#L55 when realmId is undefined.

Question is, why is it undefined? I traced it back to this line

https://github.com/realm/realm-js/blob/8c32a4c9c6bc1876dca8442d42291bae37739ff4/lib/browser/rpc.js#L335

Screenshot 2020-08-03 at 12 13 25

giniedp avatar Aug 03 '20 10:08 giniedp

once i stop debugging and close dev tools, realm picks up the node context and it works again. I haven't used devtools before. After the update devtools were enabled automatically leading me into this issue.

giniedp avatar Aug 03 '20 10:08 giniedp

Is there any progress on this issue.

utkarsh-bandekar avatar Sep 15 '21 06:09 utkarsh-bandekar

@utkarsh-bandekar We are working on a project to revisit how classes can be used for data modelling but I can't promise a release date.

kneth avatar Sep 15 '21 08:09 kneth

@kneth : We are using : "react": "16.9.0", "react-native": "^0.61.5", "realm": "^3.5.0",

We are facing issue of Typescript realm types return RealmObject not their original type only in debug mode. it works fine in non debug mode. We are totally blocked with debugging. :(

utkarsh-bandekar avatar Sep 15 '21 09:09 utkarsh-bandekar

@utkarsh-bandekar Version 3.5.0 is very old (released December 2019), and I will recommend you to upgrade.

kneth avatar Sep 15 '21 09:09 kneth

@kneth : i upgrade realm to 6.1.8 but facing same issue. There are breaking changes to upgrade 10.8.0. I could not find any reference to do the upgrade. .

utkarsh-bandekar avatar Sep 15 '21 09:09 utkarsh-bandekar

Any update on this? Facing the same issue here with;

"react": "17.0.2" "react-native": "0.66.4", "realm": "10.11.0"

anietieasuquo avatar Jan 21 '22 23:01 anietieasuquo